Skip to content

General purpose JSON viewer and editor. Built with Surplus

License

Notifications You must be signed in to change notification settings

beenotung/s-data

Repository files navigation

s-data

General purpose data viewer and editor

npm Package Version

(This package was renamed from @beenotung/s-json)

Powered by S.js and surplus

Demo: https://s-json-demo.surge.sh/

Installation

npm install s-data

Typescript Signature

declare function JsonView(props: JsonViewProps<any>): HTMLElement

declare function JsonEdit(props: JsonEditProps<any>): HTMLElement | HTMLElement[]

type JsonViewProps<T> = {
  data: T,
  name?: string
  expandElement?: boolean,
}

type JsonEditProps<T> = {
  data: T,
  name?: string
  parent?: object
  updateValue?: (value: T) => void
  onChange?: (ev: Event, detail: UpdateDetail) => void
  editElement?: boolean,
}

type UpdateDetail = {
  parent?: object
  name?: string
  oldValue: any
  newValue: any,
}

Supported Data Type

  • HTMLElement
  • Text (DOM node)
  • string
  • number
  • timestamp (in number)
  • Date
  • bigint
  • boolean
  • function (show the source code)
  • symbol
  • undefined
  • null
  • Set
  • Map
  • Array
  • object

Usage Examples

This section demo using s-json with surplus, however it is not required.

JsonEdit, JsonView are javascript functions, that upon calling, return HTMLElement(s). Hence, it can be used with plain js as well.

Sample Data:

import * as Surplus from 'surplus';
Surplus;

export let sampleData = {
  username: 'Alice',
  age: 20,                  // render as input[type=number]
  todayTime: Date.now(),    // render as input[type=date] and input[type=time]
  todayDate: new Date(),
  salary: BigInt('12345'),  // render as input[type=text]
  isActive: true,
  sym: Symbol.for('alice'),
  partner: undefined,
  task: null,
  tagSet: new Set(['app', 'developer', 'web']),
  contactMap: new Map([
    [Symbol.for('bob'), {name: 'Bob', tel: '+85298765432'}],
    [Symbol.for('cherry'), {name: 'Cherry', tel: '+85223456789'}],
  ]),
  foodArr: ['seafood', 'potato'],
  profileObj: {
    name: 'Alice',
    age: 20,
  },
  // DOM elements
  friendNodes: [
    <span style={{fontSize: 'larger'}}>Bob</span>,
    <b>Cherry</b>,
    <a href='javascript:alert("clicked")'>Dave</a>,
    document.createTextNode('Eve'),
  ],
  // function
  onMessage: (msg: string) => alert('message: ' + msg),
}

Details refer to demo-data.tsx

Usage Example of JsonView

import * as Surplus from 'surplus';
import S from 's-js';
import { JsonView } from '../src/json-view';
import { sampleData } from './demo-data';
Surplus;

S.root(() => {
  // let main = JsonView({data: sampleData}) // without jsx
  let main = <JsonView data={sampleData} />; // with jsx
  document.body.appendChild(main);
});

Usage Example of JsonEdit:

import * as Surplus from 'surplus';
import S from 's-js';
import { JsonEdit, UpdateDetail } from '../src/json-edit';
import { sampleData } from './demo-data';
Surplus;

S.root(() => {
  let lastUpdate = S.data(Date.now());

  let main = (
    <div>
      Last update: {new Date(lastUpdate()).toLocaleString()}
      <h2>JsonEdit</h2>
      {JsonEdit({
        data: sampleData,
        editElement: true,
        onChange: (ev, { parent, name, newValue, oldValue }: UpdateDetail) => {
          console.log('change', { parent, name, newValue, oldValue });
          lastUpdate(Date.now());
        },
      })}
    </div>
  );
  document.body.appendChild(main);
});

Remark

JsonEdit updates the data in-place. Therefore, if you need to use JsonView (or other elements) to display the data editing by JsonEdit on the same page, you'll need to use a change signal in the container of JsonView. For example:

import * as Surplus from 'surplus';
import S from 's-js';
import { JsonEdit } from '../src/json-edit';
import { JsonView } from '../src/json-view';
import { sampleData } from './demo-data';

Surplus;

S.root(() => {
  let lastUpdate = S.data(Date.now());

  function ChangeDetect(props: { signal: any; children: any }) {
    return props.children;
  }

  let main = (
    <div>
      Last update: {new Date(lastUpdate()).toLocaleString()}
      <div style={{ display: 'flex' }}>
        <div>
          <h2>JsonView</h2>
          <ChangeDetect signal={lastUpdate()}>
            <JsonView data={sampleData} />
          </ChangeDetect>
        </div>
        <div>
          <h2>JsonEdit</h2>
          {JsonEdit({
            data: sampleData,
            editElement: true,
            onChange: (ev, detail) => {
              console.log('change', detail);
              lastUpdate(Date.now());
            },
          })}
        </div>
      </div>
    </div>
  );
  document.body.appendChild(main);
});

Details see demo.tsx

About

General purpose JSON viewer and editor. Built with Surplus

Resources

License

Stars

Watchers

Forks

Packages

No packages published