@es-joy/jsoe 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/formats.js CHANGED
@@ -1,13 +1,17 @@
1
- import Types from './types.js';
2
- import {jml} from '../vendor/jamilih/dist/jml-es.js';
3
-
4
- import {$e, DOM} from './utils/templateUtils.js';
5
- import dialogs from './utils/dialogs.js';
6
-
7
1
  import * as indexedDBKey from './formats/indexedDBKey.js';
8
2
  import * as json from './formats/json.js';
9
3
  import * as structuredCloning from './formats/structuredCloning.js';
10
4
 
5
+ /* schema:
6
+ const getTypeForFormatStateAndValue = ({format, state, value}) => {
7
+ const valType = new Typeson().register(
8
+ structuredCloningThrowing
9
+ ).rootTypeName(value);
10
+ return canonicalToAvailableType(format, state, valType, value);
11
+ };
12
+ Formats.getTypeForFormatStateAndValue = getTypeForFormatStateAndValue;
13
+ */
14
+
11
15
  // Using methods ensure we have fresh copies
12
16
  const Formats = {
13
17
  availableFormats: {
@@ -23,207 +27,14 @@ const Formats = {
23
27
  };
24
28
 
25
29
  /**
26
- * An arbitrary Structured Clone, JSON, etc. value.
27
- * @typedef {any} StructuredCloneValue
28
- */
29
-
30
- /**
31
- * @callback BuildTypeChoices
32
- * @param {object} cfg
33
- * @param {string} cfg.format
34
- * @param {string} cfg.typeNamespace
35
- * @param {StructuredCloneValue} cfg.value
36
- * @param {boolean} [cfg.setValue=false]
37
- * @param {string} cfg.state
38
- * @param {string} cfg.keySelectClass
39
- * @param {boolean} cfg.requireObject
40
- * @param {boolean} cfg.objectHasValue
41
- * @param {RootElement} cfg.topRoot Always a `div` element?
42
- * @param {string} cfg.schema Schema name
43
- * @param {string} cfg.schemaContent Schema contents
44
- * @returns {JamilihArray}
45
- */
46
-
47
- /**
48
- * @type {BuildTypeChoices}
30
+ * @type {import('./formats/structuredCloning.js').FormatIterator}
49
31
  */
50
- const buildTypeChoices = Formats.buildTypeChoices = ({
51
- format,
52
- typeNamespace,
53
- value,
54
- setValue = false,
55
- state,
56
- // itemIndex = 0,
57
- keySelectClass,
58
- requireObject,
59
- objectHasValue,
60
- topRoot,
61
- schema,
62
- schemaContent
63
- }) => {
64
- // console.log('format', format, 'state', state, 'path', typeNamespace);
65
- const typeOptions = requireObject
66
- ? [Types.getOptionForType('object')]
67
- : Types.getTypeOptionsForFormatAndState(format, state);
68
-
69
- let editUI;
70
- const sel = jml('select', {
71
- hidden: requireObject,
72
- class: `typeChoices-${typeNamespace}${keySelectClass
73
- ? ' ' + keySelectClass
74
- : ''
75
- }`,
76
- // is: 'type-choices',
77
- $custom: {
78
- $setType ({type, baseValue, bringIntoFocus}) {
79
- this.value = type;
80
- this.$setStyles();
81
- this.$addAndValidateEditUI({baseValue, bringIntoFocus});
82
- },
83
- $setTypeNoEditUI ({type}) {
84
- this.value = type;
85
- this.$setStyles();
86
- },
87
- $setStyles () {
88
- const {value: type} = this;
89
- this.dataset.type = type; // Used for styling
90
- const parEl = this.parentElement;
91
- if (parEl.nodeName.toLowerCase() === 'fieldset') {
92
- parEl.dataset.type = type;
93
- DOM.filterChildElements(parEl, 'legend').forEach((legend) => {
94
- legend.dataset.type = type;
95
- });
96
- }
97
- },
98
- $getTypeRoot () {
99
- const container = this.$getContainer();
100
- /* istanbul ignore if -- How to replicate? */
101
- if (!container) {
102
- return false;
103
- }
104
- return $e(container, 'div[data-type]');
105
- },
106
- $addAndValidateEditUI ({baseValue, bringIntoFocus} = {}) {
107
- const {value: type} = this;
108
-
109
- const container = this.$getContainer();
110
- DOM.removeChildren(container);
111
-
112
- if (!type) { return; }
113
- let topRoot = this.$getTopRoot();
114
-
115
- // Todo (low): Try to avoid need for `baseValue`
116
- // (needed by arrayNonindexKeys for setting an array
117
- // length and avoiding errors); could set all
118
- // values through here?
119
- editUI = Types.getUIForModeAndType({
120
- readonly: false,
121
- typeNamespace,
122
- type,
123
- bringIntoFocus,
124
- hasValue: type === 'arrayNonindexKeys' && baseValue,
125
- value: baseValue,
126
- buildTypeChoices,
127
- format,
128
- topRoot
129
- });
130
- this.$addEditUI({editUI});
131
- this.$validate();
132
- topRoot = this.$getTopRoot(); // May be existing now
133
- // Needed; Array/object ref somewhere could now be valid or invalid
134
- Types.validateAllReferences({topRoot});
135
- },
136
- $addTypeAndEditUI ({type, editUI}) {
137
- this.$setTypeNoEditUI({type});
138
- this.$addEditUI({editUI});
139
- },
140
- $addEditUI ({editUI}) {
141
- const container = this.$getContainer();
142
- jml(editUI, container);
143
- },
144
- $getContainer () {
145
- return this.nextElementSibling;
146
- },
147
- $getTopRoot () {
148
- return topRoot || this.$getTypeRoot();
149
- },
150
- $validate () {
151
- const {value: type} = this;
152
- const container = this.$getContainer();
153
- if (!container.firstElementChild) {
154
- return false;
155
- }
156
- const editUI = container.firstElementChild;
157
- return Types.validate({
158
- type, root: editUI, topRoot: this.$getTopRoot()
159
- });
160
- }
161
- },
162
- $on: {change (e) {
163
- // We don't want form `onchange` to run `$checkForKeyDuplicates`
164
- // again (through `addAndValidateEditUI`->`validateAllReferences`)
165
- e.stopPropagation();
166
- this.$addAndValidateEditUI();
167
- this.$setStyles();
168
- }}
169
- }, [
170
- ['option', {value: ''}, [
171
- '(Choose a type)'
172
- ]],
173
- ...typeOptions.map(
174
- ([optText, optAtts]) => [
175
- 'option',
176
- optAtts ||
177
- /* istanbul ignore next -- Should always have atts */
178
- {},
179
- [optText]
180
- ]
181
- )
182
- ]);
183
- if (setValue || (requireObject && !objectHasValue)) {
184
- setTimeout(async () => {
185
- if (!setValue) { // if (requireObject && !objectHasValue) {
186
- // Todo (low): We could auto-populate keypath if has
187
- // keypath (and we probably also only want if
188
- // not autoincrement)
189
- value = {};
190
- }
191
- try {
192
- const rootEditUI = await Formats.availableFormats[format].iterate(
193
- value,
194
- {
195
- readonly: false,
196
- typeNamespace,
197
- schema,
198
- schemaContent
199
- }
200
- );
201
- const type = Types.getTypeForRoot(rootEditUI);
202
- sel.$addTypeAndEditUI({type, editUI: rootEditUI});
203
- } catch (err) {
204
- /* istanbul ignore next -- At least some errors handled earlier */
205
- dialogs.alert({
206
- message: 'The object to be added had types not supported ' +
207
- 'by the current format.'
208
- });
209
- /* istanbul ignore next -- How to trigger? */
210
- console.log('err', err);
211
- }
32
+ export async function getControlsForFormatAndValue (format, record, stateObj) {
33
+ return await Formats.availableFormats[format]
34
+ .iterate(record, {
35
+ format,
36
+ ...stateObj
212
37
  });
213
- }
214
- return [
215
- sel,
216
- ['div', {class: 'typeContainer'}]
217
- ];
218
- };
219
-
220
- /* schema:
221
- Formats.getTypeForFormatStateAndValue = ({format, state, value}) => {
222
- const valType = new Typeson().register(
223
- structuredCloningThrowing
224
- ).rootTypeName(value);
225
- return canonicalToAvailableType(format, state, valType, value);
226
- };
227
- */
38
+ }
228
39
 
229
40
  export default Formats;
@@ -1,7 +1,7 @@
1
1
  import {$e, $$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const BooleanObjectType = {
7
7
  option: ['BooleanObject'],
@@ -2,7 +2,7 @@ import {$e} from '../utils/templateUtils.js';
2
2
  import Types from '../types.js';
3
3
 
4
4
  /**
5
- * @type {TypeObject}
5
+ * @type {import('../types.js').TypeObject}
6
6
  */
7
7
  const NumberObjectType = {
8
8
  option: ['NumberObject'],
@@ -1,7 +1,7 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const StringObjectType = {
7
7
  stringRegex: /^String\(([^)]*)\)$/u,
@@ -5,7 +5,7 @@ import {
5
5
  } from '../utils/jsonPointer.js';
6
6
 
7
7
  /**
8
- * @type {TypeObject}
8
+ * @type {import('../types.js').TypeObject}
9
9
  */
10
10
  const arrayReferenceType = {
11
11
  option: ['Array reference'],
@@ -8,7 +8,7 @@ import {
8
8
  } from '../utils/jsonPointer.js';
9
9
 
10
10
  /**
11
- * @type {TypeObject}
11
+ * @type {import('../types.js').TypeObject}
12
12
  */
13
13
  const arrayType = {
14
14
  option: ['Array'],
@@ -646,14 +646,14 @@ const arrayType = {
646
646
  ], arrayItems);
647
647
  // We must ensure fieldset is built before passing it
648
648
  jml({'#': [
649
- ...buildTypeChoices({
649
+ ...(buildTypeChoices({
650
650
  resultType,
651
651
  topRoot,
652
652
  format,
653
653
  state: type,
654
654
  itemIndex,
655
655
  typeNamespace
656
- }),
656
+ }).domArray),
657
657
  nbsp.repeat(2),
658
658
  ['button', {$on: {click (e) {
659
659
  e.preventDefault();
@@ -1,7 +1,7 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const bigintType = {
7
7
  option: ['BigInt'],
@@ -3,7 +3,7 @@ import {jml} from '../../vendor/jamilih/dist/jml-es.js';
3
3
  import Types from '../types.js';
4
4
 
5
5
  /**
6
- * @type {TypeObject}
6
+ * @type {import('../types.js').TypeObject}
7
7
  */
8
8
  const dateType = {
9
9
  option: ['Date'],
@@ -1,7 +1,7 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const nullType = {
7
7
  option: ['Null'],
@@ -1,7 +1,7 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const numberType = {
7
7
  option: ['Number'],
@@ -1,7 +1,7 @@
1
1
  import Types from '../types.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const objectReferenceType = {
7
7
  option: ['Object reference'],
@@ -1,7 +1,7 @@
1
1
  import Types from '../types.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const objectType = {
7
7
  option: ['Object'],
@@ -3,7 +3,7 @@ import {jml} from '../../vendor/jamilih/dist/jml-es.js';
3
3
  import Types from '../types.js';
4
4
 
5
5
  /**
6
- * @type {TypeObject}
6
+ * @type {import('../types.js').TypeObject}
7
7
  */
8
8
  const regexpType = {
9
9
  option: ['RegExp'],
@@ -1,7 +1,7 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const sparseUndefinedType = {
7
7
  option: ['Sparse undefined'],
@@ -1,7 +1,7 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const stringType = {
7
7
  option: ['String'],
@@ -1,7 +1,7 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const undefinedType = {
7
7
  stringRegex: /^undefined$/u,
package/src/index.js CHANGED
@@ -1,7 +1,12 @@
1
1
  export {default as Types} from './types.js';
2
2
 
3
- export {default as Formats} from './formats.js';
3
+ export {default as Formats, getControlsForFormatAndValue} from './formats.js';
4
4
 
5
5
  export {
6
- default as typeChoices, getFormatAndSchemaChoices
6
+ buildTypeChoices as typeChoices
7
7
  } from './typeChoices.js';
8
+
9
+ export {
10
+ formatAndTypeChoices,
11
+ getFormatAndSchemaChoices
12
+ } from './formatAndTypeChoices.js';
package/src/jsoe.css ADDED
@@ -0,0 +1,58 @@
1
+ input:invalid {
2
+ background-color: pink;
3
+ }
4
+
5
+ [data-type="undef"] {
6
+ background-color: green;
7
+ }
8
+ [data-type="null"] {
9
+ background-color: lightgreen;
10
+ }
11
+ [data-type="true"] {
12
+ background-color: blue;
13
+ color: white;
14
+ }
15
+ [data-type="false"] {
16
+ background-color: pink;
17
+ }
18
+ [data-type="number"] {
19
+ background-color: violet;
20
+ }
21
+ [data-type="string"] {
22
+ background-color: lightblue;
23
+ }
24
+ [data-type="array"], [data-type="sparseArrays"], [data-type="arrayNonindexKeys"] {
25
+ background-color: lightyellow;
26
+ }
27
+ [data-type="object"] {
28
+ background-color: orange;
29
+ }
30
+
31
+
32
+ [data-type="arrayReference"] {
33
+ color: white;
34
+ background-color: indigo;
35
+ }
36
+ [data-type="objectReference"] {
37
+ color: white;
38
+ background-color: purple;
39
+ }
40
+ [data-type="date"] {
41
+ background-color: teal;
42
+ }
43
+ [data-type="regexp"] {
44
+ background-color: yellow;
45
+ }
46
+ [data-type="SpecialNumber"], [data-type="Infinities"] {
47
+ background-color: red;
48
+ }
49
+ [data-type="BooleanObject"], [data-type="NumberObject"], [data-type="StringObject"] {
50
+ background-color: aqua;
51
+ }
52
+ [data-type="blobHTML"] {
53
+ background-color: sandybrown;
54
+ }
55
+
56
+ [class^="propertyName-"] {
57
+ background-color: yellow;
58
+ }
@@ -1,7 +1,7 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const falseType = {
7
7
  option: ['Boolean (false)', {value: 'false'}],
@@ -1,7 +1,7 @@
1
1
  import {$e} from '../utils/templateUtils.js';
2
2
 
3
3
  /**
4
- * @type {TypeObject}
4
+ * @type {import('../types.js').TypeObject}
5
5
  */
6
6
  const trueType = {
7
7
  option: ['Boolean (true)', {value: 'true'}],