sygnal 4.1.0 → 4.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/README.md CHANGED
@@ -186,13 +186,23 @@ For Vite:
186
186
  // vite.config.js
187
187
  export default defineConfig({
188
188
  esbuild: {
189
- jsxInject: `import { jsx, Fragment } from 'sygnal/jsx'`,
190
- jsxFactory: 'jsx',
191
- jsxFragment: 'Fragment'
189
+ jsx: 'automatic',
190
+ jsxImportSource: 'sygnal',
192
191
  }
193
192
  })
194
193
  ```
195
194
 
195
+ For TypeScript projects, also add to `tsconfig.json`:
196
+
197
+ ```json
198
+ {
199
+ "compilerOptions": {
200
+ "jsx": "react-jsx",
201
+ "jsxImportSource": "sygnal"
202
+ }
203
+ }
204
+ ```
205
+
196
206
  Without JSX, use `h()`:
197
207
 
198
208
  ```javascript
@@ -16,8 +16,8 @@ function sygnalAstroIntegration() {
16
16
  updateConfig({
17
17
  vite: {
18
18
  esbuild: {
19
- jsxFactory: 'jsx',
20
- jsxInject: `import { jsx } from 'sygnal/jsx'`,
19
+ jsx: 'automatic',
20
+ jsxImportSource: 'sygnal',
21
21
  },
22
22
  },
23
23
  });
@@ -14,8 +14,8 @@ function sygnalAstroIntegration() {
14
14
  updateConfig({
15
15
  vite: {
16
16
  esbuild: {
17
- jsxFactory: 'jsx',
18
- jsxInject: `import { jsx } from 'sygnal/jsx'`,
17
+ jsx: 'automatic',
18
+ jsxImportSource: 'sygnal',
19
19
  },
20
20
  },
21
21
  });
@@ -0,0 +1,271 @@
1
+ 'use strict';
2
+
3
+ var _extend = require('extend');
4
+
5
+ const undefinedv = (v) => v === undefined;
6
+
7
+ const number = (v) => typeof v === 'number';
8
+
9
+ const string = (v) => typeof v === 'string';
10
+
11
+ const text = (v) => string(v) || number(v);
12
+
13
+ const array = (v) => Array.isArray(v);
14
+
15
+ const object = (v) => typeof v === 'object' && v !== null;
16
+
17
+ const fun = (v) => typeof v === 'function';
18
+
19
+ const vnode$1 = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v;
20
+
21
+ const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
22
+ polyline: 1, rect: 1, g: 1, path: 1, text: 1 };
23
+
24
+ const svg = (v) => v.sel in svgPropsMap;
25
+
26
+ // TODO: stop using extend here
27
+
28
+ const extend = (...objs) => _extend(true, ...objs);
29
+
30
+ const assign = (...objs) => _extend(false, ...objs);
31
+
32
+ const reduceDeep = (arr, fn, initial) => {
33
+ let result = initial;
34
+ for (let i = 0; i < arr.length; i++) {
35
+ const value = arr[i];
36
+ if (array(value)) {
37
+ result = reduceDeep(value, fn, result);
38
+ } else {
39
+ result = fn(result, value);
40
+ }
41
+ }
42
+ return result
43
+ };
44
+
45
+ const mapObject = (obj, fn) => Object.keys(obj).map(
46
+ (key) => fn(key, obj[key])
47
+ ).reduce(
48
+ (acc, curr) => extend(acc, curr),
49
+ {}
50
+ );
51
+
52
+ const deepifyKeys = (obj, modules) => mapObject(obj,
53
+ (key, val) => {
54
+ const dashIndex = key.indexOf('-');
55
+ if (dashIndex > -1 && modules[key.slice(0, dashIndex)] !== undefined) {
56
+ const moduleData = {
57
+ [key.slice(dashIndex + 1)]: val
58
+ };
59
+ return {
60
+ [key.slice(0, dashIndex)]: moduleData
61
+ }
62
+ }
63
+ return { [key]: val }
64
+ }
65
+ );
66
+
67
+ const omit = (key, obj) => mapObject(obj,
68
+ (mod, data) => mod !== key ? ({ [mod]: data }) : {}
69
+ );
70
+
71
+ // Const fnName = (...params) => guard ? default : ...
72
+
73
+ const createTextElement = (text$1) => !text(text$1) ? undefined : {
74
+ text: text$1,
75
+ sel: undefined,
76
+ data: undefined,
77
+ children: undefined,
78
+ elm: undefined,
79
+ key: undefined
80
+ };
81
+
82
+ const considerSvg = (vnode) => !svg(vnode) ? vnode :
83
+ assign(vnode,
84
+ { data: omit('props', extend(vnode.data,
85
+ { ns: 'http://www.w3.org/2000/svg', attrs: omit('className', extend(vnode.data.props,
86
+ { class: vnode.data.props ? vnode.data.props.className : undefined }
87
+ )) }
88
+ )) },
89
+ { children: undefinedv(vnode.children) ? undefined :
90
+ vnode.children.map((child) => considerSvg(child))
91
+ }
92
+ );
93
+
94
+ const rewrites = {
95
+ for: 'attrs',
96
+ role: 'attrs',
97
+ tabindex: 'attrs',
98
+ 'aria-*': 'attrs',
99
+ key: null
100
+ };
101
+
102
+ const rewriteModules = (data, modules) => mapObject(data, (key, val) => {
103
+ const inner = { [key]: val };
104
+ if (rewrites[key] && modules[rewrites[key]] !== undefined) {
105
+ return { [rewrites[key]]: inner }
106
+ }
107
+ if (rewrites[key] === null) {
108
+ return {}
109
+ }
110
+ const keys = Object.keys(rewrites);
111
+ for (let i = 0; i < keys.length; i++) {
112
+ const k = keys[i];
113
+ if (k.charAt(k.length - 1) === '*' && key.indexOf(k.slice(0, -1)) === 0 && modules[rewrites[k]] !== undefined) {
114
+ return { [rewrites[k]]: inner }
115
+ }
116
+ }
117
+ if (modules[key] !== undefined) {
118
+ return { [modules[key] ? modules[key] : key]: val }
119
+ }
120
+ if (modules.props !== undefined) {
121
+ return { props: inner }
122
+ }
123
+ return inner
124
+ });
125
+
126
+ const applyFocusProps = (data) => {
127
+ if (!data.props) return data
128
+ const { autoFocus, autoSelect, ...rest } = data.props;
129
+ if (!autoFocus && !autoSelect) return data
130
+
131
+ data.props = rest;
132
+ const existingInsert = data.hook?.insert;
133
+ data.hook = {
134
+ ...data.hook,
135
+ insert: (vnode) => {
136
+ if (existingInsert) existingInsert(vnode);
137
+ if (vnode.elm && typeof vnode.elm.focus === 'function') {
138
+ vnode.elm.focus();
139
+ if (autoSelect && typeof vnode.elm.select === 'function') {
140
+ vnode.elm.select();
141
+ }
142
+ }
143
+ },
144
+ };
145
+ return data
146
+ };
147
+
148
+ const sanitizeData = (data, modules) => applyFocusProps(considerSvg(rewriteModules(deepifyKeys(data, modules), modules)));
149
+
150
+ const sanitizeText = (children) => children.length > 1 || !text(children[0]) ? undefined : children[0].toString();
151
+
152
+ const sanitizeChildren = (children) => reduceDeep(children, (acc, child) => {
153
+ const vnode = vnode$1(child) ? child : createTextElement(child);
154
+ acc.push(vnode);
155
+ return acc
156
+ }
157
+ , []);
158
+
159
+ const defaultModules = {
160
+ attrs: '',
161
+ props: '',
162
+ class: '',
163
+ data: 'dataset',
164
+ style: '',
165
+ hook: '',
166
+ on: ''
167
+ };
168
+
169
+ const createElementWithModules = (modules) => {
170
+ return (sel, data, ...children) => {
171
+ if (typeof sel === 'undefined') {
172
+ sel = 'UNDEFINED';
173
+ console.error('JSX Error: Capitalized HTML element without corresponding factory function. Components with names where the first letter is capital MUST be defined or included at the parent component\'s file scope.');
174
+ }
175
+ if (fun(sel)) {
176
+ if (sel.name === 'Fragment') {
177
+ return sel(data || {}, children)
178
+ }
179
+ data ||= {};
180
+ if (!sel.isSygnalComponent) {
181
+ const name = sel.componentName || sel.label || sel.name || 'FUNCTION_COMPONENT';
182
+ const view = sel;
183
+ const { model, intent, hmrActions, context, peers, components, initialState, calculated, storeCalculatedInState, DOMSourceName, stateSourceName, debug, preventInstantiation } = sel;
184
+ if (preventInstantiation) {
185
+ const text = sanitizeText(children);
186
+ return considerSvg({
187
+ sel: name,
188
+ data: data ? sanitizeData(data, modules) : {},
189
+ children: typeof text !== 'undefined' ? createTextElement(text) : sanitizeChildren(children),
190
+ text,
191
+ elm: undefined,
192
+ key: data ? data.key : undefined
193
+ })
194
+ }
195
+ const options = { name, view, model, intent, hmrActions, context, peers, components, initialState, calculated, storeCalculatedInState, DOMSourceName, stateSourceName, debug };
196
+ data.sygnalOptions = options;
197
+ sel = name;
198
+ } else {
199
+ const factory = sel;
200
+ sel = sel.componentName || sel.label || sel.name || 'sygnal-factory';
201
+ data.sygnalFactory = factory;
202
+ }
203
+ }
204
+ const text = sanitizeText(children);
205
+ return considerSvg({
206
+ sel,
207
+ data: data ? sanitizeData(data, modules) : {},
208
+ children: typeof text !== 'undefined' ? createTextElement(text) : sanitizeChildren(children),
209
+ text,
210
+ elm: undefined,
211
+ key: data ? data.key : undefined
212
+ })
213
+ }
214
+ };
215
+
216
+ const createElement = createElementWithModules(defaultModules);
217
+
218
+ function vnode(sel, data, children, text, elm) {
219
+ const key = data === undefined ? undefined : data.key;
220
+ return { sel, data, children, text, elm, key };
221
+ }
222
+
223
+ /* eslint-disable @typescript-eslint/no-namespace, import/export */
224
+ function Fragment(data, ...children) {
225
+ const flatChildren = flattenAndFilter(children, []);
226
+ if (flatChildren.length === 1 &&
227
+ !flatChildren[0].sel &&
228
+ flatChildren[0].text) {
229
+ // only child is a simple text node, pass as text for a simpler vtree
230
+ return vnode(undefined, undefined, undefined, flatChildren[0].text, undefined);
231
+ }
232
+ else {
233
+ return vnode(undefined, data !== null && data !== void 0 ? data : {}, flatChildren, undefined, undefined);
234
+ }
235
+ }
236
+ function flattenAndFilter(children, flattened) {
237
+ for (const child of children) {
238
+ // filter out falsey children, except 0 since zero can be a valid value e.g inside a chart
239
+ if (child !== undefined &&
240
+ child !== null &&
241
+ child !== false &&
242
+ child !== "") {
243
+ if (Array.isArray(child)) {
244
+ flattenAndFilter(child, flattened);
245
+ }
246
+ else if (typeof child === "string" ||
247
+ typeof child === "number" ||
248
+ typeof child === "boolean") {
249
+ flattened.push(vnode(undefined, undefined, undefined, String(child), undefined));
250
+ }
251
+ else {
252
+ flattened.push(child);
253
+ }
254
+ }
255
+ }
256
+ return flattened;
257
+ }
258
+
259
+ function jsx(type, props, key) {
260
+ if (props == null) return createElement(type, null)
261
+ const { children, ...rest } = props;
262
+ if (key !== undefined) rest.key = key;
263
+ if (children === undefined) return createElement(type, rest)
264
+ if (Array.isArray(children)) return createElement(type, rest, ...children)
265
+ return createElement(type, rest, children)
266
+ }
267
+
268
+ exports.Fragment = Fragment;
269
+ exports.jsx = jsx;
270
+ exports.jsxDEV = jsx;
271
+ exports.jsxs = jsx;
@@ -0,0 +1,266 @@
1
+ import _extend from 'extend';
2
+
3
+ const undefinedv = (v) => v === undefined;
4
+
5
+ const number = (v) => typeof v === 'number';
6
+
7
+ const string = (v) => typeof v === 'string';
8
+
9
+ const text = (v) => string(v) || number(v);
10
+
11
+ const array = (v) => Array.isArray(v);
12
+
13
+ const object = (v) => typeof v === 'object' && v !== null;
14
+
15
+ const fun = (v) => typeof v === 'function';
16
+
17
+ const vnode$1 = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v;
18
+
19
+ const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
20
+ polyline: 1, rect: 1, g: 1, path: 1, text: 1 };
21
+
22
+ const svg = (v) => v.sel in svgPropsMap;
23
+
24
+ // TODO: stop using extend here
25
+
26
+ const extend = (...objs) => _extend(true, ...objs);
27
+
28
+ const assign = (...objs) => _extend(false, ...objs);
29
+
30
+ const reduceDeep = (arr, fn, initial) => {
31
+ let result = initial;
32
+ for (let i = 0; i < arr.length; i++) {
33
+ const value = arr[i];
34
+ if (array(value)) {
35
+ result = reduceDeep(value, fn, result);
36
+ } else {
37
+ result = fn(result, value);
38
+ }
39
+ }
40
+ return result
41
+ };
42
+
43
+ const mapObject = (obj, fn) => Object.keys(obj).map(
44
+ (key) => fn(key, obj[key])
45
+ ).reduce(
46
+ (acc, curr) => extend(acc, curr),
47
+ {}
48
+ );
49
+
50
+ const deepifyKeys = (obj, modules) => mapObject(obj,
51
+ (key, val) => {
52
+ const dashIndex = key.indexOf('-');
53
+ if (dashIndex > -1 && modules[key.slice(0, dashIndex)] !== undefined) {
54
+ const moduleData = {
55
+ [key.slice(dashIndex + 1)]: val
56
+ };
57
+ return {
58
+ [key.slice(0, dashIndex)]: moduleData
59
+ }
60
+ }
61
+ return { [key]: val }
62
+ }
63
+ );
64
+
65
+ const omit = (key, obj) => mapObject(obj,
66
+ (mod, data) => mod !== key ? ({ [mod]: data }) : {}
67
+ );
68
+
69
+ // Const fnName = (...params) => guard ? default : ...
70
+
71
+ const createTextElement = (text$1) => !text(text$1) ? undefined : {
72
+ text: text$1,
73
+ sel: undefined,
74
+ data: undefined,
75
+ children: undefined,
76
+ elm: undefined,
77
+ key: undefined
78
+ };
79
+
80
+ const considerSvg = (vnode) => !svg(vnode) ? vnode :
81
+ assign(vnode,
82
+ { data: omit('props', extend(vnode.data,
83
+ { ns: 'http://www.w3.org/2000/svg', attrs: omit('className', extend(vnode.data.props,
84
+ { class: vnode.data.props ? vnode.data.props.className : undefined }
85
+ )) }
86
+ )) },
87
+ { children: undefinedv(vnode.children) ? undefined :
88
+ vnode.children.map((child) => considerSvg(child))
89
+ }
90
+ );
91
+
92
+ const rewrites = {
93
+ for: 'attrs',
94
+ role: 'attrs',
95
+ tabindex: 'attrs',
96
+ 'aria-*': 'attrs',
97
+ key: null
98
+ };
99
+
100
+ const rewriteModules = (data, modules) => mapObject(data, (key, val) => {
101
+ const inner = { [key]: val };
102
+ if (rewrites[key] && modules[rewrites[key]] !== undefined) {
103
+ return { [rewrites[key]]: inner }
104
+ }
105
+ if (rewrites[key] === null) {
106
+ return {}
107
+ }
108
+ const keys = Object.keys(rewrites);
109
+ for (let i = 0; i < keys.length; i++) {
110
+ const k = keys[i];
111
+ if (k.charAt(k.length - 1) === '*' && key.indexOf(k.slice(0, -1)) === 0 && modules[rewrites[k]] !== undefined) {
112
+ return { [rewrites[k]]: inner }
113
+ }
114
+ }
115
+ if (modules[key] !== undefined) {
116
+ return { [modules[key] ? modules[key] : key]: val }
117
+ }
118
+ if (modules.props !== undefined) {
119
+ return { props: inner }
120
+ }
121
+ return inner
122
+ });
123
+
124
+ const applyFocusProps = (data) => {
125
+ if (!data.props) return data
126
+ const { autoFocus, autoSelect, ...rest } = data.props;
127
+ if (!autoFocus && !autoSelect) return data
128
+
129
+ data.props = rest;
130
+ const existingInsert = data.hook?.insert;
131
+ data.hook = {
132
+ ...data.hook,
133
+ insert: (vnode) => {
134
+ if (existingInsert) existingInsert(vnode);
135
+ if (vnode.elm && typeof vnode.elm.focus === 'function') {
136
+ vnode.elm.focus();
137
+ if (autoSelect && typeof vnode.elm.select === 'function') {
138
+ vnode.elm.select();
139
+ }
140
+ }
141
+ },
142
+ };
143
+ return data
144
+ };
145
+
146
+ const sanitizeData = (data, modules) => applyFocusProps(considerSvg(rewriteModules(deepifyKeys(data, modules), modules)));
147
+
148
+ const sanitizeText = (children) => children.length > 1 || !text(children[0]) ? undefined : children[0].toString();
149
+
150
+ const sanitizeChildren = (children) => reduceDeep(children, (acc, child) => {
151
+ const vnode = vnode$1(child) ? child : createTextElement(child);
152
+ acc.push(vnode);
153
+ return acc
154
+ }
155
+ , []);
156
+
157
+ const defaultModules = {
158
+ attrs: '',
159
+ props: '',
160
+ class: '',
161
+ data: 'dataset',
162
+ style: '',
163
+ hook: '',
164
+ on: ''
165
+ };
166
+
167
+ const createElementWithModules = (modules) => {
168
+ return (sel, data, ...children) => {
169
+ if (typeof sel === 'undefined') {
170
+ sel = 'UNDEFINED';
171
+ console.error('JSX Error: Capitalized HTML element without corresponding factory function. Components with names where the first letter is capital MUST be defined or included at the parent component\'s file scope.');
172
+ }
173
+ if (fun(sel)) {
174
+ if (sel.name === 'Fragment') {
175
+ return sel(data || {}, children)
176
+ }
177
+ data ||= {};
178
+ if (!sel.isSygnalComponent) {
179
+ const name = sel.componentName || sel.label || sel.name || 'FUNCTION_COMPONENT';
180
+ const view = sel;
181
+ const { model, intent, hmrActions, context, peers, components, initialState, calculated, storeCalculatedInState, DOMSourceName, stateSourceName, debug, preventInstantiation } = sel;
182
+ if (preventInstantiation) {
183
+ const text = sanitizeText(children);
184
+ return considerSvg({
185
+ sel: name,
186
+ data: data ? sanitizeData(data, modules) : {},
187
+ children: typeof text !== 'undefined' ? createTextElement(text) : sanitizeChildren(children),
188
+ text,
189
+ elm: undefined,
190
+ key: data ? data.key : undefined
191
+ })
192
+ }
193
+ const options = { name, view, model, intent, hmrActions, context, peers, components, initialState, calculated, storeCalculatedInState, DOMSourceName, stateSourceName, debug };
194
+ data.sygnalOptions = options;
195
+ sel = name;
196
+ } else {
197
+ const factory = sel;
198
+ sel = sel.componentName || sel.label || sel.name || 'sygnal-factory';
199
+ data.sygnalFactory = factory;
200
+ }
201
+ }
202
+ const text = sanitizeText(children);
203
+ return considerSvg({
204
+ sel,
205
+ data: data ? sanitizeData(data, modules) : {},
206
+ children: typeof text !== 'undefined' ? createTextElement(text) : sanitizeChildren(children),
207
+ text,
208
+ elm: undefined,
209
+ key: data ? data.key : undefined
210
+ })
211
+ }
212
+ };
213
+
214
+ const createElement = createElementWithModules(defaultModules);
215
+
216
+ function vnode(sel, data, children, text, elm) {
217
+ const key = data === undefined ? undefined : data.key;
218
+ return { sel, data, children, text, elm, key };
219
+ }
220
+
221
+ /* eslint-disable @typescript-eslint/no-namespace, import/export */
222
+ function Fragment(data, ...children) {
223
+ const flatChildren = flattenAndFilter(children, []);
224
+ if (flatChildren.length === 1 &&
225
+ !flatChildren[0].sel &&
226
+ flatChildren[0].text) {
227
+ // only child is a simple text node, pass as text for a simpler vtree
228
+ return vnode(undefined, undefined, undefined, flatChildren[0].text, undefined);
229
+ }
230
+ else {
231
+ return vnode(undefined, data !== null && data !== void 0 ? data : {}, flatChildren, undefined, undefined);
232
+ }
233
+ }
234
+ function flattenAndFilter(children, flattened) {
235
+ for (const child of children) {
236
+ // filter out falsey children, except 0 since zero can be a valid value e.g inside a chart
237
+ if (child !== undefined &&
238
+ child !== null &&
239
+ child !== false &&
240
+ child !== "") {
241
+ if (Array.isArray(child)) {
242
+ flattenAndFilter(child, flattened);
243
+ }
244
+ else if (typeof child === "string" ||
245
+ typeof child === "number" ||
246
+ typeof child === "boolean") {
247
+ flattened.push(vnode(undefined, undefined, undefined, String(child), undefined));
248
+ }
249
+ else {
250
+ flattened.push(child);
251
+ }
252
+ }
253
+ }
254
+ return flattened;
255
+ }
256
+
257
+ function jsx(type, props, key) {
258
+ if (props == null) return createElement(type, null)
259
+ const { children, ...rest } = props;
260
+ if (key !== undefined) rest.key = key;
261
+ if (children === undefined) return createElement(type, rest)
262
+ if (Array.isArray(children)) return createElement(type, rest, ...children)
263
+ return createElement(type, rest, children)
264
+ }
265
+
266
+ export { Fragment, jsx, jsx as jsxDEV, jsx as jsxs };
@@ -0,0 +1,271 @@
1
+ 'use strict';
2
+
3
+ var _extend = require('extend');
4
+
5
+ const undefinedv = (v) => v === undefined;
6
+
7
+ const number = (v) => typeof v === 'number';
8
+
9
+ const string = (v) => typeof v === 'string';
10
+
11
+ const text = (v) => string(v) || number(v);
12
+
13
+ const array = (v) => Array.isArray(v);
14
+
15
+ const object = (v) => typeof v === 'object' && v !== null;
16
+
17
+ const fun = (v) => typeof v === 'function';
18
+
19
+ const vnode$1 = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v;
20
+
21
+ const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
22
+ polyline: 1, rect: 1, g: 1, path: 1, text: 1 };
23
+
24
+ const svg = (v) => v.sel in svgPropsMap;
25
+
26
+ // TODO: stop using extend here
27
+
28
+ const extend = (...objs) => _extend(true, ...objs);
29
+
30
+ const assign = (...objs) => _extend(false, ...objs);
31
+
32
+ const reduceDeep = (arr, fn, initial) => {
33
+ let result = initial;
34
+ for (let i = 0; i < arr.length; i++) {
35
+ const value = arr[i];
36
+ if (array(value)) {
37
+ result = reduceDeep(value, fn, result);
38
+ } else {
39
+ result = fn(result, value);
40
+ }
41
+ }
42
+ return result
43
+ };
44
+
45
+ const mapObject = (obj, fn) => Object.keys(obj).map(
46
+ (key) => fn(key, obj[key])
47
+ ).reduce(
48
+ (acc, curr) => extend(acc, curr),
49
+ {}
50
+ );
51
+
52
+ const deepifyKeys = (obj, modules) => mapObject(obj,
53
+ (key, val) => {
54
+ const dashIndex = key.indexOf('-');
55
+ if (dashIndex > -1 && modules[key.slice(0, dashIndex)] !== undefined) {
56
+ const moduleData = {
57
+ [key.slice(dashIndex + 1)]: val
58
+ };
59
+ return {
60
+ [key.slice(0, dashIndex)]: moduleData
61
+ }
62
+ }
63
+ return { [key]: val }
64
+ }
65
+ );
66
+
67
+ const omit = (key, obj) => mapObject(obj,
68
+ (mod, data) => mod !== key ? ({ [mod]: data }) : {}
69
+ );
70
+
71
+ // Const fnName = (...params) => guard ? default : ...
72
+
73
+ const createTextElement = (text$1) => !text(text$1) ? undefined : {
74
+ text: text$1,
75
+ sel: undefined,
76
+ data: undefined,
77
+ children: undefined,
78
+ elm: undefined,
79
+ key: undefined
80
+ };
81
+
82
+ const considerSvg = (vnode) => !svg(vnode) ? vnode :
83
+ assign(vnode,
84
+ { data: omit('props', extend(vnode.data,
85
+ { ns: 'http://www.w3.org/2000/svg', attrs: omit('className', extend(vnode.data.props,
86
+ { class: vnode.data.props ? vnode.data.props.className : undefined }
87
+ )) }
88
+ )) },
89
+ { children: undefinedv(vnode.children) ? undefined :
90
+ vnode.children.map((child) => considerSvg(child))
91
+ }
92
+ );
93
+
94
+ const rewrites = {
95
+ for: 'attrs',
96
+ role: 'attrs',
97
+ tabindex: 'attrs',
98
+ 'aria-*': 'attrs',
99
+ key: null
100
+ };
101
+
102
+ const rewriteModules = (data, modules) => mapObject(data, (key, val) => {
103
+ const inner = { [key]: val };
104
+ if (rewrites[key] && modules[rewrites[key]] !== undefined) {
105
+ return { [rewrites[key]]: inner }
106
+ }
107
+ if (rewrites[key] === null) {
108
+ return {}
109
+ }
110
+ const keys = Object.keys(rewrites);
111
+ for (let i = 0; i < keys.length; i++) {
112
+ const k = keys[i];
113
+ if (k.charAt(k.length - 1) === '*' && key.indexOf(k.slice(0, -1)) === 0 && modules[rewrites[k]] !== undefined) {
114
+ return { [rewrites[k]]: inner }
115
+ }
116
+ }
117
+ if (modules[key] !== undefined) {
118
+ return { [modules[key] ? modules[key] : key]: val }
119
+ }
120
+ if (modules.props !== undefined) {
121
+ return { props: inner }
122
+ }
123
+ return inner
124
+ });
125
+
126
+ const applyFocusProps = (data) => {
127
+ if (!data.props) return data
128
+ const { autoFocus, autoSelect, ...rest } = data.props;
129
+ if (!autoFocus && !autoSelect) return data
130
+
131
+ data.props = rest;
132
+ const existingInsert = data.hook?.insert;
133
+ data.hook = {
134
+ ...data.hook,
135
+ insert: (vnode) => {
136
+ if (existingInsert) existingInsert(vnode);
137
+ if (vnode.elm && typeof vnode.elm.focus === 'function') {
138
+ vnode.elm.focus();
139
+ if (autoSelect && typeof vnode.elm.select === 'function') {
140
+ vnode.elm.select();
141
+ }
142
+ }
143
+ },
144
+ };
145
+ return data
146
+ };
147
+
148
+ const sanitizeData = (data, modules) => applyFocusProps(considerSvg(rewriteModules(deepifyKeys(data, modules), modules)));
149
+
150
+ const sanitizeText = (children) => children.length > 1 || !text(children[0]) ? undefined : children[0].toString();
151
+
152
+ const sanitizeChildren = (children) => reduceDeep(children, (acc, child) => {
153
+ const vnode = vnode$1(child) ? child : createTextElement(child);
154
+ acc.push(vnode);
155
+ return acc
156
+ }
157
+ , []);
158
+
159
+ const defaultModules = {
160
+ attrs: '',
161
+ props: '',
162
+ class: '',
163
+ data: 'dataset',
164
+ style: '',
165
+ hook: '',
166
+ on: ''
167
+ };
168
+
169
+ const createElementWithModules = (modules) => {
170
+ return (sel, data, ...children) => {
171
+ if (typeof sel === 'undefined') {
172
+ sel = 'UNDEFINED';
173
+ console.error('JSX Error: Capitalized HTML element without corresponding factory function. Components with names where the first letter is capital MUST be defined or included at the parent component\'s file scope.');
174
+ }
175
+ if (fun(sel)) {
176
+ if (sel.name === 'Fragment') {
177
+ return sel(data || {}, children)
178
+ }
179
+ data ||= {};
180
+ if (!sel.isSygnalComponent) {
181
+ const name = sel.componentName || sel.label || sel.name || 'FUNCTION_COMPONENT';
182
+ const view = sel;
183
+ const { model, intent, hmrActions, context, peers, components, initialState, calculated, storeCalculatedInState, DOMSourceName, stateSourceName, debug, preventInstantiation } = sel;
184
+ if (preventInstantiation) {
185
+ const text = sanitizeText(children);
186
+ return considerSvg({
187
+ sel: name,
188
+ data: data ? sanitizeData(data, modules) : {},
189
+ children: typeof text !== 'undefined' ? createTextElement(text) : sanitizeChildren(children),
190
+ text,
191
+ elm: undefined,
192
+ key: data ? data.key : undefined
193
+ })
194
+ }
195
+ const options = { name, view, model, intent, hmrActions, context, peers, components, initialState, calculated, storeCalculatedInState, DOMSourceName, stateSourceName, debug };
196
+ data.sygnalOptions = options;
197
+ sel = name;
198
+ } else {
199
+ const factory = sel;
200
+ sel = sel.componentName || sel.label || sel.name || 'sygnal-factory';
201
+ data.sygnalFactory = factory;
202
+ }
203
+ }
204
+ const text = sanitizeText(children);
205
+ return considerSvg({
206
+ sel,
207
+ data: data ? sanitizeData(data, modules) : {},
208
+ children: typeof text !== 'undefined' ? createTextElement(text) : sanitizeChildren(children),
209
+ text,
210
+ elm: undefined,
211
+ key: data ? data.key : undefined
212
+ })
213
+ }
214
+ };
215
+
216
+ const createElement = createElementWithModules(defaultModules);
217
+
218
+ function vnode(sel, data, children, text, elm) {
219
+ const key = data === undefined ? undefined : data.key;
220
+ return { sel, data, children, text, elm, key };
221
+ }
222
+
223
+ /* eslint-disable @typescript-eslint/no-namespace, import/export */
224
+ function Fragment(data, ...children) {
225
+ const flatChildren = flattenAndFilter(children, []);
226
+ if (flatChildren.length === 1 &&
227
+ !flatChildren[0].sel &&
228
+ flatChildren[0].text) {
229
+ // only child is a simple text node, pass as text for a simpler vtree
230
+ return vnode(undefined, undefined, undefined, flatChildren[0].text, undefined);
231
+ }
232
+ else {
233
+ return vnode(undefined, data !== null && data !== void 0 ? data : {}, flatChildren, undefined, undefined);
234
+ }
235
+ }
236
+ function flattenAndFilter(children, flattened) {
237
+ for (const child of children) {
238
+ // filter out falsey children, except 0 since zero can be a valid value e.g inside a chart
239
+ if (child !== undefined &&
240
+ child !== null &&
241
+ child !== false &&
242
+ child !== "") {
243
+ if (Array.isArray(child)) {
244
+ flattenAndFilter(child, flattened);
245
+ }
246
+ else if (typeof child === "string" ||
247
+ typeof child === "number" ||
248
+ typeof child === "boolean") {
249
+ flattened.push(vnode(undefined, undefined, undefined, String(child), undefined));
250
+ }
251
+ else {
252
+ flattened.push(child);
253
+ }
254
+ }
255
+ }
256
+ return flattened;
257
+ }
258
+
259
+ function jsx(type, props, key) {
260
+ if (props == null) return createElement(type, null)
261
+ const { children, ...rest } = props;
262
+ if (key !== undefined) rest.key = key;
263
+ if (children === undefined) return createElement(type, rest)
264
+ if (Array.isArray(children)) return createElement(type, rest, ...children)
265
+ return createElement(type, rest, children)
266
+ }
267
+
268
+ exports.Fragment = Fragment;
269
+ exports.jsx = jsx;
270
+ exports.jsxDEV = jsx;
271
+ exports.jsxs = jsx;
@@ -0,0 +1,266 @@
1
+ import _extend from 'extend';
2
+
3
+ const undefinedv = (v) => v === undefined;
4
+
5
+ const number = (v) => typeof v === 'number';
6
+
7
+ const string = (v) => typeof v === 'string';
8
+
9
+ const text = (v) => string(v) || number(v);
10
+
11
+ const array = (v) => Array.isArray(v);
12
+
13
+ const object = (v) => typeof v === 'object' && v !== null;
14
+
15
+ const fun = (v) => typeof v === 'function';
16
+
17
+ const vnode$1 = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v;
18
+
19
+ const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
20
+ polyline: 1, rect: 1, g: 1, path: 1, text: 1 };
21
+
22
+ const svg = (v) => v.sel in svgPropsMap;
23
+
24
+ // TODO: stop using extend here
25
+
26
+ const extend = (...objs) => _extend(true, ...objs);
27
+
28
+ const assign = (...objs) => _extend(false, ...objs);
29
+
30
+ const reduceDeep = (arr, fn, initial) => {
31
+ let result = initial;
32
+ for (let i = 0; i < arr.length; i++) {
33
+ const value = arr[i];
34
+ if (array(value)) {
35
+ result = reduceDeep(value, fn, result);
36
+ } else {
37
+ result = fn(result, value);
38
+ }
39
+ }
40
+ return result
41
+ };
42
+
43
+ const mapObject = (obj, fn) => Object.keys(obj).map(
44
+ (key) => fn(key, obj[key])
45
+ ).reduce(
46
+ (acc, curr) => extend(acc, curr),
47
+ {}
48
+ );
49
+
50
+ const deepifyKeys = (obj, modules) => mapObject(obj,
51
+ (key, val) => {
52
+ const dashIndex = key.indexOf('-');
53
+ if (dashIndex > -1 && modules[key.slice(0, dashIndex)] !== undefined) {
54
+ const moduleData = {
55
+ [key.slice(dashIndex + 1)]: val
56
+ };
57
+ return {
58
+ [key.slice(0, dashIndex)]: moduleData
59
+ }
60
+ }
61
+ return { [key]: val }
62
+ }
63
+ );
64
+
65
+ const omit = (key, obj) => mapObject(obj,
66
+ (mod, data) => mod !== key ? ({ [mod]: data }) : {}
67
+ );
68
+
69
+ // Const fnName = (...params) => guard ? default : ...
70
+
71
+ const createTextElement = (text$1) => !text(text$1) ? undefined : {
72
+ text: text$1,
73
+ sel: undefined,
74
+ data: undefined,
75
+ children: undefined,
76
+ elm: undefined,
77
+ key: undefined
78
+ };
79
+
80
+ const considerSvg = (vnode) => !svg(vnode) ? vnode :
81
+ assign(vnode,
82
+ { data: omit('props', extend(vnode.data,
83
+ { ns: 'http://www.w3.org/2000/svg', attrs: omit('className', extend(vnode.data.props,
84
+ { class: vnode.data.props ? vnode.data.props.className : undefined }
85
+ )) }
86
+ )) },
87
+ { children: undefinedv(vnode.children) ? undefined :
88
+ vnode.children.map((child) => considerSvg(child))
89
+ }
90
+ );
91
+
92
+ const rewrites = {
93
+ for: 'attrs',
94
+ role: 'attrs',
95
+ tabindex: 'attrs',
96
+ 'aria-*': 'attrs',
97
+ key: null
98
+ };
99
+
100
+ const rewriteModules = (data, modules) => mapObject(data, (key, val) => {
101
+ const inner = { [key]: val };
102
+ if (rewrites[key] && modules[rewrites[key]] !== undefined) {
103
+ return { [rewrites[key]]: inner }
104
+ }
105
+ if (rewrites[key] === null) {
106
+ return {}
107
+ }
108
+ const keys = Object.keys(rewrites);
109
+ for (let i = 0; i < keys.length; i++) {
110
+ const k = keys[i];
111
+ if (k.charAt(k.length - 1) === '*' && key.indexOf(k.slice(0, -1)) === 0 && modules[rewrites[k]] !== undefined) {
112
+ return { [rewrites[k]]: inner }
113
+ }
114
+ }
115
+ if (modules[key] !== undefined) {
116
+ return { [modules[key] ? modules[key] : key]: val }
117
+ }
118
+ if (modules.props !== undefined) {
119
+ return { props: inner }
120
+ }
121
+ return inner
122
+ });
123
+
124
+ const applyFocusProps = (data) => {
125
+ if (!data.props) return data
126
+ const { autoFocus, autoSelect, ...rest } = data.props;
127
+ if (!autoFocus && !autoSelect) return data
128
+
129
+ data.props = rest;
130
+ const existingInsert = data.hook?.insert;
131
+ data.hook = {
132
+ ...data.hook,
133
+ insert: (vnode) => {
134
+ if (existingInsert) existingInsert(vnode);
135
+ if (vnode.elm && typeof vnode.elm.focus === 'function') {
136
+ vnode.elm.focus();
137
+ if (autoSelect && typeof vnode.elm.select === 'function') {
138
+ vnode.elm.select();
139
+ }
140
+ }
141
+ },
142
+ };
143
+ return data
144
+ };
145
+
146
+ const sanitizeData = (data, modules) => applyFocusProps(considerSvg(rewriteModules(deepifyKeys(data, modules), modules)));
147
+
148
+ const sanitizeText = (children) => children.length > 1 || !text(children[0]) ? undefined : children[0].toString();
149
+
150
+ const sanitizeChildren = (children) => reduceDeep(children, (acc, child) => {
151
+ const vnode = vnode$1(child) ? child : createTextElement(child);
152
+ acc.push(vnode);
153
+ return acc
154
+ }
155
+ , []);
156
+
157
+ const defaultModules = {
158
+ attrs: '',
159
+ props: '',
160
+ class: '',
161
+ data: 'dataset',
162
+ style: '',
163
+ hook: '',
164
+ on: ''
165
+ };
166
+
167
+ const createElementWithModules = (modules) => {
168
+ return (sel, data, ...children) => {
169
+ if (typeof sel === 'undefined') {
170
+ sel = 'UNDEFINED';
171
+ console.error('JSX Error: Capitalized HTML element without corresponding factory function. Components with names where the first letter is capital MUST be defined or included at the parent component\'s file scope.');
172
+ }
173
+ if (fun(sel)) {
174
+ if (sel.name === 'Fragment') {
175
+ return sel(data || {}, children)
176
+ }
177
+ data ||= {};
178
+ if (!sel.isSygnalComponent) {
179
+ const name = sel.componentName || sel.label || sel.name || 'FUNCTION_COMPONENT';
180
+ const view = sel;
181
+ const { model, intent, hmrActions, context, peers, components, initialState, calculated, storeCalculatedInState, DOMSourceName, stateSourceName, debug, preventInstantiation } = sel;
182
+ if (preventInstantiation) {
183
+ const text = sanitizeText(children);
184
+ return considerSvg({
185
+ sel: name,
186
+ data: data ? sanitizeData(data, modules) : {},
187
+ children: typeof text !== 'undefined' ? createTextElement(text) : sanitizeChildren(children),
188
+ text,
189
+ elm: undefined,
190
+ key: data ? data.key : undefined
191
+ })
192
+ }
193
+ const options = { name, view, model, intent, hmrActions, context, peers, components, initialState, calculated, storeCalculatedInState, DOMSourceName, stateSourceName, debug };
194
+ data.sygnalOptions = options;
195
+ sel = name;
196
+ } else {
197
+ const factory = sel;
198
+ sel = sel.componentName || sel.label || sel.name || 'sygnal-factory';
199
+ data.sygnalFactory = factory;
200
+ }
201
+ }
202
+ const text = sanitizeText(children);
203
+ return considerSvg({
204
+ sel,
205
+ data: data ? sanitizeData(data, modules) : {},
206
+ children: typeof text !== 'undefined' ? createTextElement(text) : sanitizeChildren(children),
207
+ text,
208
+ elm: undefined,
209
+ key: data ? data.key : undefined
210
+ })
211
+ }
212
+ };
213
+
214
+ const createElement = createElementWithModules(defaultModules);
215
+
216
+ function vnode(sel, data, children, text, elm) {
217
+ const key = data === undefined ? undefined : data.key;
218
+ return { sel, data, children, text, elm, key };
219
+ }
220
+
221
+ /* eslint-disable @typescript-eslint/no-namespace, import/export */
222
+ function Fragment(data, ...children) {
223
+ const flatChildren = flattenAndFilter(children, []);
224
+ if (flatChildren.length === 1 &&
225
+ !flatChildren[0].sel &&
226
+ flatChildren[0].text) {
227
+ // only child is a simple text node, pass as text for a simpler vtree
228
+ return vnode(undefined, undefined, undefined, flatChildren[0].text, undefined);
229
+ }
230
+ else {
231
+ return vnode(undefined, data !== null && data !== void 0 ? data : {}, flatChildren, undefined, undefined);
232
+ }
233
+ }
234
+ function flattenAndFilter(children, flattened) {
235
+ for (const child of children) {
236
+ // filter out falsey children, except 0 since zero can be a valid value e.g inside a chart
237
+ if (child !== undefined &&
238
+ child !== null &&
239
+ child !== false &&
240
+ child !== "") {
241
+ if (Array.isArray(child)) {
242
+ flattenAndFilter(child, flattened);
243
+ }
244
+ else if (typeof child === "string" ||
245
+ typeof child === "number" ||
246
+ typeof child === "boolean") {
247
+ flattened.push(vnode(undefined, undefined, undefined, String(child), undefined));
248
+ }
249
+ else {
250
+ flattened.push(child);
251
+ }
252
+ }
253
+ }
254
+ return flattened;
255
+ }
256
+
257
+ function jsx(type, props, key) {
258
+ if (props == null) return createElement(type, null)
259
+ const { children, ...rest } = props;
260
+ if (key !== undefined) rest.key = key;
261
+ if (children === undefined) return createElement(type, rest)
262
+ if (Array.isArray(children)) return createElement(type, rest, ...children)
263
+ return createElement(type, rest, children)
264
+ }
265
+
266
+ export { Fragment, jsx, jsx as jsxDEV, jsx as jsxs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sygnal",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "An intuitive framework for building fast and small components or applications based on Cycle.js",
5
5
  "main": "./dist/index.cjs.js",
6
6
  "types": "./dist/index.d.ts",
@@ -12,10 +12,20 @@
12
12
  "require": "./dist/index.cjs.js"
13
13
  },
14
14
  "./jsx": {
15
- "types": "./dist/index.d.ts",
15
+ "types": "./src/jsx.d.ts",
16
16
  "import": "./dist/jsx.esm.js",
17
17
  "require": "./dist/jsx.cjs.js"
18
18
  },
19
+ "./jsx-runtime": {
20
+ "types": "./src/jsx-runtime.d.ts",
21
+ "import": "./dist/jsx-runtime.esm.js",
22
+ "require": "./dist/jsx-runtime.cjs.js"
23
+ },
24
+ "./jsx-dev-runtime": {
25
+ "types": "./src/jsx-runtime.d.ts",
26
+ "import": "./dist/jsx-dev-runtime.esm.js",
27
+ "require": "./dist/jsx-dev-runtime.cjs.js"
28
+ },
19
29
  "./astro": {
20
30
  "types": "./src/astro/index.d.ts",
21
31
  "import": "./dist/astro/index.mjs",
@@ -14,8 +14,8 @@ export default function sygnalAstroIntegration() {
14
14
  updateConfig({
15
15
  vite: {
16
16
  esbuild: {
17
- jsxFactory: 'jsx',
18
- jsxInject: `import { jsx } from 'sygnal/jsx'`,
17
+ jsx: 'automatic',
18
+ jsxImportSource: 'sygnal',
19
19
  },
20
20
  },
21
21
  })
@@ -0,0 +1 @@
1
+ export { jsx, jsxs, jsxDEV, Fragment } from './jsx-runtime'
@@ -0,0 +1,4 @@
1
+ export declare function jsx(type: any, props: any, key?: any): any
2
+ export declare function jsxs(type: any, props: any, key?: any): any
3
+ export declare function jsxDEV(type: any, props: any, key?: any): any
4
+ export declare function Fragment(data: any, ...children: any[]): any
@@ -0,0 +1,14 @@
1
+ import { createElement } from './pragma/index'
2
+ export { Fragment } from 'snabbdom'
3
+
4
+ export function jsx(type, props, key) {
5
+ if (props == null) return createElement(type, null)
6
+ const { children, ...rest } = props
7
+ if (key !== undefined) rest.key = key
8
+ if (children === undefined) return createElement(type, rest)
9
+ if (Array.isArray(children)) return createElement(type, rest, ...children)
10
+ return createElement(type, rest, children)
11
+ }
12
+
13
+ export { jsx as jsxs }
14
+ export { jsx as jsxDEV }
package/src/jsx.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { createElement as jsx } from './pragma/index';
2
+ export declare function Fragment(data: any, children: any[]): any;
@@ -0,0 +1,2 @@
1
+ export declare function createElement(sel: any, data: any, ...children: any[]): any;
2
+ export declare function createElementWithModules(modules: any): (sel: any, data: any, ...children: any[]) => any;