@livenetworks/ashlar 2.0.6 → 2.0.8
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/LICENSE +641 -641
- package/components/COMPONENTS.md +1116 -1116
- package/components/index.js +81 -81
- package/components/ln-accordion/ln-accordion-dev.scss +8 -8
- package/components/ln-accordion/ln-accordion.js +1 -1
- package/components/ln-accordion/ln-accordion.schema.json +30 -30
- package/components/ln-accordion/src/ln-accordion.js +1 -0
- package/components/ln-ajax/ln-ajax-dev.scss +8 -8
- package/components/ln-ajax/ln-ajax.js +1 -1
- package/components/ln-ajax/ln-ajax.schema.json +30 -30
- package/components/ln-api-connector/ln-api-connector.js +1 -1
- package/components/ln-api-connector/ln-api-connector.schema.json +96 -96
- package/components/ln-api-connector/src/ln-api-connector.js +1 -0
- package/components/ln-api-queue/ln-api-queue.js +1 -1
- package/components/ln-api-queue/ln-api-queue.schema.json +34 -34
- package/components/ln-api-queue/src/ln-api-queue.js +3 -13
- package/components/ln-autoresize/ln-autoresize-dev.scss +8 -8
- package/components/ln-autoresize/ln-autoresize.js +1 -1
- package/components/ln-autoresize/ln-autoresize.schema.json +22 -22
- package/components/ln-autosave/ln-autosave-dev.scss +13 -13
- package/components/ln-autosave/ln-autosave.js +1 -1
- package/components/ln-autosave/ln-autosave.schema.json +48 -48
- package/components/ln-autosave/src/autosave-model.js +34 -34
- package/components/ln-chart/ln-chart.js +1 -1
- package/components/ln-chart/ln-chart.schema.json +146 -146
- package/components/ln-chart/src/chart-model.js +154 -154
- package/components/ln-circular-progress/ln-circular-progress.js +1 -1
- package/components/ln-circular-progress/ln-circular-progress.schema.json +42 -42
- package/components/ln-confirm/ln-confirm-dev.scss +24 -24
- package/components/ln-confirm/ln-confirm.js +1 -1
- package/components/ln-confirm/ln-confirm.schema.json +66 -66
- package/components/ln-confirm/src/ln-confirm.js +178 -178
- package/components/ln-core/crypto.js +286 -265
- package/components/ln-core/dom.js +115 -115
- package/components/ln-core/form.js +136 -136
- package/components/ln-core/helpers.js +33 -33
- package/components/ln-core/http.js +48 -48
- package/components/ln-core/index.js +1 -1
- package/components/ln-core/ln-core.schema.json +109 -109
- package/components/ln-core/locale.js +55 -55
- package/components/ln-core/matching.js +78 -78
- package/components/ln-core/number.js +125 -125
- package/components/ln-core/template.js +206 -206
- package/components/ln-couchdb-connector/README.md +4 -0
- package/components/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
- package/components/ln-couchdb-connector/ln-couchdb-connector.schema.json +50 -50
- package/components/ln-couchdb-connector/src/ln-couchdb-connector.js +19 -1
- package/components/ln-data-coordinator/README.md +9 -38
- package/components/ln-data-coordinator/ln-data-coordinator-dev.scss +8 -8
- package/components/ln-data-coordinator/ln-data-coordinator.js +1 -1
- package/components/ln-data-coordinator/ln-data-coordinator.schema.json +16 -16
- package/components/ln-data-coordinator/src/data-read-policy.js +0 -7
- package/components/ln-data-coordinator/src/ln-data-coordinator.js +428 -1299
- package/components/ln-data-store/README.md +3 -2
- package/components/ln-data-store/ln-data-store-dev.scss +13 -13
- package/components/ln-data-store/ln-data-store.js +1 -1
- package/components/ln-data-store/ln-data-store.schema.json +84 -84
- package/components/ln-data-store/src/data-store-model.js +184 -155
- package/components/ln-data-store/src/ln-data-store.js +58 -11
- package/components/ln-date/README.md +4 -0
- package/components/ln-date/ln-date.js +1 -1
- package/components/ln-date/ln-date.schema.json +92 -92
- package/components/ln-date/src/date-model.js +186 -186
- package/components/ln-date/src/ln-date.js +3 -3
- package/components/ln-debug/ln-debug.js +1 -1
- package/components/ln-debug/ln-debug.schema.json +28 -28
- package/components/ln-debug/src/console-sink.js +19 -19
- package/components/ln-debug/src/gate.js +95 -95
- package/components/ln-debug/src/generated-attributes.js +2 -2
- package/components/ln-dropdown/ln-dropdown-dev.scss +13 -13
- package/components/ln-dropdown/ln-dropdown.js +1 -1
- package/components/ln-dropdown/ln-dropdown.schema.json +90 -90
- package/components/ln-editor/ln-editor.js +1 -1
- package/components/ln-editor/ln-editor.schema.json +58 -58
- package/components/ln-external-links/ln-external-links.js +1 -1
- package/components/ln-external-links/ln-external-links.schema.json +18 -18
- package/components/ln-fill/ln-fill.js +1 -1
- package/components/ln-fill/ln-fill.schema.json +23 -23
- package/components/ln-filter/ln-filter.js +1 -1
- package/components/ln-filter/ln-filter.schema.json +153 -153
- package/components/ln-filter/src/filter-model.js +185 -185
- package/components/ln-form/ln-form-dev.scss +8 -8
- package/components/ln-form/ln-form.js +1 -1
- package/components/ln-form/ln-form.schema.json +45 -45
- package/components/ln-http/ln-http.js +1 -1
- package/components/ln-http/ln-http.schema.json +6 -6
- package/components/ln-icon/ln-icon.schema.json +6 -6
- package/components/ln-include/ln-include.js +1 -1
- package/components/ln-include/ln-include.schema.json +23 -23
- package/components/ln-key/ln-key-dev.scss +18 -18
- package/components/ln-key/ln-key.js +1 -1
- package/components/ln-key/ln-key.schema.json +56 -56
- package/components/ln-key/src/ln-key.js +10 -10
- package/components/ln-link/ln-link-dev.scss +8 -8
- package/components/ln-link/ln-link.js +1 -1
- package/components/ln-link/ln-link.schema.json +22 -22
- package/components/ln-list/README.md +152 -152
- package/components/ln-list/ln-list-dev.scss +8 -8
- package/components/ln-list/ln-list.js +1 -1
- package/components/ln-list/ln-list.schema.json +166 -166
- package/components/ln-list/src/ln-list.js +4 -4
- package/components/ln-modal/README.md +4 -6
- package/components/ln-modal/ln-modal.js +1 -1
- package/components/ln-modal/ln-modal.schema.json +65 -65
- package/components/ln-modal/src/ln-modal.js +28 -8
- package/components/ln-nav/ln-nav.js +1 -1
- package/components/ln-nav/ln-nav.schema.json +25 -25
- package/components/ln-number/ln-number.js +1 -1
- package/components/ln-number/ln-number.schema.json +63 -63
- package/components/ln-number/src/number-model.js +31 -31
- package/components/ln-obfuscator/README.md +60 -60
- package/components/ln-obfuscator/ln-obfuscator.js +1 -1
- package/components/ln-obfuscator/ln-obfuscator.schema.json +49 -49
- package/components/ln-obfuscator/src/ln-obfuscator.js +159 -159
- package/components/ln-obfuscator/src/obfuscator-model.js +250 -250
- package/components/ln-options/ln-options.js +1 -1
- package/components/ln-options/ln-options.schema.json +41 -41
- package/components/ln-options/src/ln-options.js +1 -0
- package/components/ln-persist/README.md +151 -151
- package/components/ln-persist/ln-persist.js +1 -1
- package/components/ln-persist/ln-persist.schema.json +28 -28
- package/components/ln-persist/src/ln-persist.js +83 -83
- package/components/ln-picklist/README.md +230 -230
- package/components/ln-picklist/ln-picklist-dev.scss +22 -22
- package/components/ln-picklist/ln-picklist.js +1 -1
- package/components/ln-picklist/ln-picklist.schema.json +49 -49
- package/components/ln-picklist/src/ln-picklist.js +228 -228
- package/components/ln-popover/README.md +4 -0
- package/components/ln-popover/ln-popover-dev.scss +13 -13
- package/components/ln-popover/ln-popover.js +1 -1
- package/components/ln-popover/ln-popover.schema.json +82 -82
- package/components/ln-popover/src/ln-popover.js +9 -0
- package/components/ln-progress/ln-progress-dev.scss +8 -8
- package/components/ln-progress/ln-progress.js +1 -1
- package/components/ln-progress/ln-progress.schema.json +40 -40
- package/components/ln-router/ln-router.js +1 -1
- package/components/ln-router/ln-router.schema.json +76 -76
- package/components/ln-scroll/README.md +45 -45
- package/components/ln-scroll/ln-scroll.js +1 -1
- package/components/ln-scroll/ln-scroll.schema.json +85 -85
- package/components/ln-scroll/src/ln-scroll.js +150 -150
- package/components/ln-search/README.md +188 -188
- package/components/ln-search/ln-search.js +1 -1
- package/components/ln-search/ln-search.schema.json +103 -103
- package/components/ln-slug/ln-slug.js +1 -1
- package/components/ln-slug/ln-slug.schema.json +23 -23
- package/components/ln-sort/ln-sort.js +1 -1
- package/components/ln-sort/ln-sort.schema.json +104 -104
- package/components/ln-sort/src/ln-sort.js +321 -321
- package/components/ln-sort/src/sort-model.js +117 -117
- package/components/ln-sortable/ln-sortable-dev.scss +13 -13
- package/components/ln-sortable/ln-sortable.js +1 -1
- package/components/ln-sortable/ln-sortable.schema.json +36 -36
- package/components/ln-stat/ln-stat-dev.scss +8 -8
- package/components/ln-stat/ln-stat.js +1 -1
- package/components/ln-stat/ln-stat.schema.json +32 -32
- package/components/ln-stat/src/stat-model.js +28 -28
- package/components/ln-table/ln-table.js +1 -1
- package/components/ln-table/ln-table.schema.json +211 -211
- package/components/ln-table/src/ln-table.js +2 -0
- package/components/ln-table/src/table-model.js +98 -98
- package/components/ln-table-coordinator/ln-table-coordinator.js +1 -1
- package/components/ln-table-coordinator/ln-table-coordinator.schema.json +93 -93
- package/components/ln-table-coordinator/src/ln-table-coordinator.js +3 -3
- package/components/ln-tabs/README.md +2 -2
- package/components/ln-tabs/ln-tabs.js +1 -1
- package/components/ln-tabs/ln-tabs.schema.json +75 -75
- package/components/ln-tabs/src/ln-tabs.js +208 -207
- package/components/ln-tabs/src/tabs-model.js +82 -82
- package/components/ln-time/ln-time-dev.scss +13 -13
- package/components/ln-time/ln-time.js +1 -1
- package/components/ln-time/ln-time.schema.json +38 -38
- package/components/ln-toast/ln-toast.js +1 -1
- package/components/ln-toast/ln-toast.schema.json +65 -65
- package/components/ln-toggle/ln-toggle.js +1 -1
- package/components/ln-toggle/ln-toggle.schema.json +52 -52
- package/components/ln-tooltip/ln-tooltip.js +1 -1
- package/components/ln-tooltip/ln-tooltip.schema.json +86 -86
- package/components/ln-translations/ln-translations.js +1 -1
- package/components/ln-translations/ln-translations.schema.json +120 -120
- package/components/ln-ui-coordinator/README.md +62 -62
- package/components/ln-ui-coordinator/ln-ui-coordinator.js +1 -1
- package/components/ln-ui-coordinator/ln-ui-coordinator.schema.json +28 -28
- package/components/ln-ui-coordinator/src/ln-ui-coordinator.js +140 -140
- package/components/ln-upload/ln-upload.js +1 -1
- package/components/ln-upload/ln-upload.schema.json +193 -193
- package/components/ln-upload/src/upload-model.js +78 -78
- package/components/ln-validate/ln-validate.js +1 -1
- package/components/ln-validate/ln-validate.schema.json +50 -50
- package/components/ln-validate/src/validate-model.js +64 -64
- package/components/ln-websocket-connector/README.md +166 -166
- package/components/ln-websocket-connector/ln-websocket-connector.js +1 -1
- package/components/ln-websocket-connector/ln-websocket-connector.schema.json +29 -29
- package/components/ln-websocket-connector/src/ln-websocket-connector.js +283 -279
- package/ln-ashlar.html-data.json +7 -8
- package/package.json +84 -84
- package/theme/brand.css +73 -73
- package/theme/components/_confirm.scss +6 -6
- package/theme/components/_picklist.scss +3 -3
- package/theme/config/_palette.scss +274 -274
- package/theme/config/_theme.scss +292 -292
- package/theme/config/_tokens.scss +285 -285
- package/theme/config/mixins/_index.scss +62 -62
- package/theme/config/mixins/_picklist.scss +66 -66
- package/theme/ln-ashlar-dev.scss +66 -66
- package/theme/ln-ashlar-landing.scss +56 -56
- package/theme/ln-ashlar-theme.scss +63 -63
- package/theme/presentation/_bento.scss +151 -151
- package/theme/presentation/_cta.scss +111 -111
- package/theme/presentation/_effects.scss +216 -216
- package/theme/presentation/_features.scss +108 -108
- package/theme/presentation/_footer.scss +129 -129
- package/theme/presentation/_hero.scss +158 -158
- package/theme/presentation/_layout.scss +170 -170
- package/theme/presentation/_navbar.scss +140 -140
- package/theme/presentation/_pricing.scss +262 -262
- package/theme/presentation/_stats.scss +87 -87
- package/theme/presentation/_testimonials.scss +124 -124
- package/theme/presentation/_tokens.scss +39 -39
- package/theme/presentation/_typography.scss +163 -163
- package/web-types.json +12 -12
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$comment": "This file is partly generated. The $comment, component, generator, and each attribute's direction, sources, type, values, fallback, and description keys are owned by the generator and synchronized from JS source code. All other keys are preserved and safe to hand-author. Regenerate with `npm run sync:ln-schemas`.",
|
|
3
|
-
"component": "ln-validate",
|
|
4
|
-
"generator": "scripts/sync-ln-schemas.mjs",
|
|
5
|
-
"attributes": {
|
|
6
|
-
"data-ln-debug": {
|
|
7
|
-
"direction": null,
|
|
8
|
-
"sources": [
|
|
9
|
-
"ln-validate-dev.scss"
|
|
10
|
-
]
|
|
11
|
-
},
|
|
12
|
-
"data-ln-error": {
|
|
13
|
-
"direction": null,
|
|
14
|
-
"sources": [
|
|
15
|
-
"ln-validate.scss"
|
|
16
|
-
]
|
|
17
|
-
},
|
|
18
|
-
"data-ln-form": {
|
|
19
|
-
"direction": null,
|
|
20
|
-
"sources": [
|
|
21
|
-
"ln-validate-dev.scss"
|
|
22
|
-
]
|
|
23
|
-
},
|
|
24
|
-
"data-ln-validate": {
|
|
25
|
-
"direction": null,
|
|
26
|
-
"sources": [
|
|
27
|
-
"ln-validate-dev.scss",
|
|
28
|
-
"src/ln-validate.js"
|
|
29
|
-
],
|
|
30
|
-
"type": "marker",
|
|
31
|
-
"description": "Activates validation on form input or field"
|
|
32
|
-
},
|
|
33
|
-
"data-ln-validate-error": {
|
|
34
|
-
"direction": "author",
|
|
35
|
-
"sources": [
|
|
36
|
-
"src/ln-validate.js"
|
|
37
|
-
],
|
|
38
|
-
"type": "string",
|
|
39
|
-
"description": "Identifies error message template for a specific validation rule"
|
|
40
|
-
},
|
|
41
|
-
"data-ln-validate-errors": {
|
|
42
|
-
"direction": "author",
|
|
43
|
-
"sources": [
|
|
44
|
-
"src/ln-validate.js"
|
|
45
|
-
],
|
|
46
|
-
"type": "marker",
|
|
47
|
-
"description": "Container element holding validation error message elements"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"$comment": "This file is partly generated. The $comment, component, generator, and each attribute's direction, sources, type, values, fallback, and description keys are owned by the generator and synchronized from JS source code. All other keys are preserved and safe to hand-author. Regenerate with `npm run sync:ln-schemas`.",
|
|
3
|
+
"component": "ln-validate",
|
|
4
|
+
"generator": "scripts/sync-ln-schemas.mjs",
|
|
5
|
+
"attributes": {
|
|
6
|
+
"data-ln-debug": {
|
|
7
|
+
"direction": null,
|
|
8
|
+
"sources": [
|
|
9
|
+
"ln-validate-dev.scss"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"data-ln-error": {
|
|
13
|
+
"direction": null,
|
|
14
|
+
"sources": [
|
|
15
|
+
"ln-validate.scss"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"data-ln-form": {
|
|
19
|
+
"direction": null,
|
|
20
|
+
"sources": [
|
|
21
|
+
"ln-validate-dev.scss"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
"data-ln-validate": {
|
|
25
|
+
"direction": null,
|
|
26
|
+
"sources": [
|
|
27
|
+
"ln-validate-dev.scss",
|
|
28
|
+
"src/ln-validate.js"
|
|
29
|
+
],
|
|
30
|
+
"type": "marker",
|
|
31
|
+
"description": "Activates validation on form input or field"
|
|
32
|
+
},
|
|
33
|
+
"data-ln-validate-error": {
|
|
34
|
+
"direction": "author",
|
|
35
|
+
"sources": [
|
|
36
|
+
"src/ln-validate.js"
|
|
37
|
+
],
|
|
38
|
+
"type": "string",
|
|
39
|
+
"description": "Identifies error message template for a specific validation rule"
|
|
40
|
+
},
|
|
41
|
+
"data-ln-validate-errors": {
|
|
42
|
+
"direction": "author",
|
|
43
|
+
"sources": [
|
|
44
|
+
"src/ln-validate.js"
|
|
45
|
+
],
|
|
46
|
+
"type": "marker",
|
|
47
|
+
"description": "Container element holding validation error message elements"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
export const ERROR_MAP = {
|
|
2
|
-
required: 'valueMissing',
|
|
3
|
-
typeMismatch: 'typeMismatch',
|
|
4
|
-
tooShort: 'tooShort',
|
|
5
|
-
tooLong: 'tooLong',
|
|
6
|
-
patternMismatch: 'patternMismatch',
|
|
7
|
-
rangeUnderflow: 'rangeUnderflow',
|
|
8
|
-
rangeOverflow: 'rangeOverflow'
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Checks if a field is valid given its native validity state and custom errors count.
|
|
13
|
-
* @param {{ valid?: boolean } | null | undefined} validityState
|
|
14
|
-
* @param {number} [customErrorsCount=0]
|
|
15
|
-
* @returns {boolean}
|
|
16
|
-
*/
|
|
17
|
-
export function isFieldValid(validityState, customErrorsCount = 0) {
|
|
18
|
-
if (!validityState) return customErrorsCount === 0;
|
|
19
|
-
return Boolean(validityState.valid && customErrorsCount === 0);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Whether a field already holds a value at init, so it is validated up front.
|
|
24
|
-
* A checkbox or radio always carries a `value` ("on" by default) — only its
|
|
25
|
-
* `checked` state says whether anything was chosen.
|
|
26
|
-
* @param {{ type?: string, value?: string, checked?: boolean }} field
|
|
27
|
-
* @returns {boolean}
|
|
28
|
-
*/
|
|
29
|
-
export function hasInitialValue(field) {
|
|
30
|
-
if (field.type === 'checkbox' || field.type === 'radio') return Boolean(field.checked);
|
|
31
|
-
return Boolean(field.value && field.value.trim() !== '');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Resolves all active error keys for a given validity state and custom errors set.
|
|
36
|
-
* @param {Record<string, boolean>} validityState
|
|
37
|
-
* @param {Set<string>|Array<string>} [customErrors]
|
|
38
|
-
* @returns {string[]}
|
|
39
|
-
*/
|
|
40
|
-
export function resolveActiveErrorKeys(validityState, customErrors) {
|
|
41
|
-
const active = [];
|
|
42
|
-
|
|
43
|
-
if (validityState) {
|
|
44
|
-
const keys = Object.keys(ERROR_MAP);
|
|
45
|
-
for (let i = 0; i < keys.length; i++) {
|
|
46
|
-
const errorKey = keys[i];
|
|
47
|
-
const prop = ERROR_MAP[errorKey];
|
|
48
|
-
if (validityState[prop]) {
|
|
49
|
-
active.push(errorKey);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (customErrors) {
|
|
55
|
-
const customList = Array.from(customErrors);
|
|
56
|
-
for (let i = 0; i < customList.length; i++) {
|
|
57
|
-
if (customList[i] && active.indexOf(customList[i]) === -1) {
|
|
58
|
-
active.push(customList[i]);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return active;
|
|
64
|
-
}
|
|
1
|
+
export const ERROR_MAP = {
|
|
2
|
+
required: 'valueMissing',
|
|
3
|
+
typeMismatch: 'typeMismatch',
|
|
4
|
+
tooShort: 'tooShort',
|
|
5
|
+
tooLong: 'tooLong',
|
|
6
|
+
patternMismatch: 'patternMismatch',
|
|
7
|
+
rangeUnderflow: 'rangeUnderflow',
|
|
8
|
+
rangeOverflow: 'rangeOverflow'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Checks if a field is valid given its native validity state and custom errors count.
|
|
13
|
+
* @param {{ valid?: boolean } | null | undefined} validityState
|
|
14
|
+
* @param {number} [customErrorsCount=0]
|
|
15
|
+
* @returns {boolean}
|
|
16
|
+
*/
|
|
17
|
+
export function isFieldValid(validityState, customErrorsCount = 0) {
|
|
18
|
+
if (!validityState) return customErrorsCount === 0;
|
|
19
|
+
return Boolean(validityState.valid && customErrorsCount === 0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Whether a field already holds a value at init, so it is validated up front.
|
|
24
|
+
* A checkbox or radio always carries a `value` ("on" by default) — only its
|
|
25
|
+
* `checked` state says whether anything was chosen.
|
|
26
|
+
* @param {{ type?: string, value?: string, checked?: boolean }} field
|
|
27
|
+
* @returns {boolean}
|
|
28
|
+
*/
|
|
29
|
+
export function hasInitialValue(field) {
|
|
30
|
+
if (field.type === 'checkbox' || field.type === 'radio') return Boolean(field.checked);
|
|
31
|
+
return Boolean(field.value && field.value.trim() !== '');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Resolves all active error keys for a given validity state and custom errors set.
|
|
36
|
+
* @param {Record<string, boolean>} validityState
|
|
37
|
+
* @param {Set<string>|Array<string>} [customErrors]
|
|
38
|
+
* @returns {string[]}
|
|
39
|
+
*/
|
|
40
|
+
export function resolveActiveErrorKeys(validityState, customErrors) {
|
|
41
|
+
const active = [];
|
|
42
|
+
|
|
43
|
+
if (validityState) {
|
|
44
|
+
const keys = Object.keys(ERROR_MAP);
|
|
45
|
+
for (let i = 0; i < keys.length; i++) {
|
|
46
|
+
const errorKey = keys[i];
|
|
47
|
+
const prop = ERROR_MAP[errorKey];
|
|
48
|
+
if (validityState[prop]) {
|
|
49
|
+
active.push(errorKey);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (customErrors) {
|
|
55
|
+
const customList = Array.from(customErrors);
|
|
56
|
+
for (let i = 0; i < customList.length; i++) {
|
|
57
|
+
if (customList[i] && active.indexOf(customList[i]) === -1) {
|
|
58
|
+
active.push(customList[i]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return active;
|
|
64
|
+
}
|
|
@@ -1,166 +1,166 @@
|
|
|
1
|
-
# `data-ln-websocket-connector`
|
|
2
|
-
|
|
3
|
-
> Applied to an element inside a `ln-data-coordinator`. Opens a WebSocket, turns server pushes into
|
|
4
|
-
> `ln-websocket-connector:fetched`, and answers the same request events as `ln-api-connector` and
|
|
5
|
-
> `ln-couchdb-connector`. Connection status is private state announced by events — never an attribute.
|
|
6
|
-
|
|
7
|
-
A zero-dependency push transport. Beside a REST connector it only delivers live changes; on its own
|
|
8
|
-
it carries reads, writes and pushes over one socket.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Declarative DOM Setup
|
|
13
|
-
|
|
14
|
-
### Live changes beside REST
|
|
15
|
-
|
|
16
|
-
The REST connector takes every request; the socket only pushes changes into the store.
|
|
17
|
-
|
|
18
|
-
```html
|
|
19
|
-
<ul data-ln-data-coordinator="tasks" hidden>
|
|
20
|
-
<li data-ln-data-store="tasks" id="tasks"></li>
|
|
21
|
-
<li data-ln-api-connector data-ln-api-base-url="https://api.example.com" data-ln-api-path="tasks"></li>
|
|
22
|
-
<li data-ln-websocket-connector data-ln-websocket-connector-url="wss://api.example.com/live"></li>
|
|
23
|
-
</ul>
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### Socket alone
|
|
27
|
-
|
|
28
|
-
With no REST or CouchDB connector in the coordinator, the socket takes every request too.
|
|
29
|
-
|
|
30
|
-
```html
|
|
31
|
-
<ul data-ln-data-coordinator="tasks" hidden>
|
|
32
|
-
<li data-ln-data-store="tasks" id="tasks"></li>
|
|
33
|
-
<li data-ln-websocket-connector data-ln-websocket-connector-url="wss://api.example.com/live"></li>
|
|
34
|
-
</ul>
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## Attributes
|
|
40
|
-
|
|
41
|
-
Both attributes are commands set from outside; the component obeys them.
|
|
42
|
-
|
|
43
|
-
| Attribute | Values | Default | Description |
|
|
44
|
-
|-----------|--------|---------|-------------|
|
|
45
|
-
| `data-ln-websocket-connector` | `connect` \| `disconnect` | `connect` | Opens or closes the socket. A bare attribute connects. |
|
|
46
|
-
| `data-ln-websocket-connector-url` | `ws://…` \| `wss://…` | — | Endpoint. Changing it while connected closes and reopens on the new URL. |
|
|
47
|
-
|
|
48
|
-
There is no attribute for the connection status. `connecting`, `connected` and `disconnected` are
|
|
49
|
-
what the component observes, not something anyone can set — writing `connected` into an attribute
|
|
50
|
-
would not connect anything. The status is announced by events; whoever listens decides how to show it.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## DOM Events
|
|
55
|
-
|
|
56
|
-
### Commands (dispatched TO the connector)
|
|
57
|
-
|
|
58
|
-
Only the `ln-websocket-connector:*` namespace is handled.
|
|
59
|
-
|
|
60
|
-
| Event | `detail` | Description |
|
|
61
|
-
|-------|----------|-------------|
|
|
62
|
-
| `ln-websocket-connector:request-sync` | `{ since, meta? }` | Delta sync since a token. |
|
|
63
|
-
| `ln-websocket-connector:request-query` | `{ query, meta? }` | One page of a query (`search`, `filters`, `sort`, `offset`, `limit`). |
|
|
64
|
-
| `ln-websocket-connector:request-create` | `{ data, tempId?, idempotencyKey?, meta? }` | Create a record. |
|
|
65
|
-
| `ln-websocket-connector:request-update` | `{ id, data, expected_version?, idempotencyKey?, meta? }` | Update a record. |
|
|
66
|
-
| `ln-websocket-connector:request-delete` | `{ id, idempotencyKey?, meta? }` | Delete a record. |
|
|
67
|
-
| `ln-websocket-connector:request-bulk-delete` | `{ ids, idempotencyKey?, meta? }` | Delete several records. |
|
|
68
|
-
|
|
69
|
-
### Notifications (emitted BY the connector)
|
|
70
|
-
|
|
71
|
-
| Event | `detail` | Description |
|
|
72
|
-
|-------|----------|-------------|
|
|
73
|
-
| `ln-websocket-connector:connecting` | `{ url, attempt }` | A connection attempt starts. `attempt` counts from 1 and resets on open. |
|
|
74
|
-
| `ln-websocket-connector:connected` | `{ url }` | The socket is open. |
|
|
75
|
-
| `ln-websocket-connector:disconnected` | `{ url, code, reason, willReconnect }` | The socket closed, or a pending reconnect was cancelled. |
|
|
76
|
-
| `ln-websocket-connector:fetched` | `{ data, since, meta }` / `{ data, total, filtered, offset, queryGen, meta }` | A sync reply, a query page, or a server push (`meta: null`). |
|
|
77
|
-
| `ln-websocket-connector:created` | `{ record, tempId, message, meta }` | Create confirmed. |
|
|
78
|
-
| `ln-websocket-connector:updated` | `{ record, id, message, meta }` | Update confirmed. |
|
|
79
|
-
| `ln-websocket-connector:deleted` | `{ response, id, message, meta }` | Delete confirmed. |
|
|
80
|
-
| `ln-websocket-connector:bulk-deleted` | `{ response, ids, message, meta }` | Bulk delete confirmed. |
|
|
81
|
-
| `ln-websocket-connector:error` | `{ action, error, status, data, conflictData, meta, … }` | A rejected request, or one that could not be delivered (`status: 0`). |
|
|
82
|
-
|
|
83
|
-
`meta` is echoed unchanged and never leaves the page.
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## Wire Protocol
|
|
88
|
-
|
|
89
|
-
JSON text frames.
|
|
90
|
-
|
|
91
|
-
**Request** — `{ "ref": "<string>", "type": "<type>", ...payload }`
|
|
92
|
-
|
|
93
|
-
| `type` | payload |
|
|
94
|
-
|--------|---------|
|
|
95
|
-
| `sync` | `since` |
|
|
96
|
-
| `query` | `query` |
|
|
97
|
-
| `create` | `data`, `idempotencyKey` |
|
|
98
|
-
| `update` | `id`, `data`, `expected_version`, `idempotencyKey` |
|
|
99
|
-
| `delete` | `id`, `idempotencyKey` |
|
|
100
|
-
| `bulk-delete` | `ids`, `idempotencyKey` |
|
|
101
|
-
|
|
102
|
-
**Reply** — the same `ref`, then either `{ "ok": true, "content": …, "message": … }` or
|
|
103
|
-
`{ "ok": false, "status": 409, "error": "…", "data": … }`. `content` is `{ data, deleted, synced_at }`
|
|
104
|
-
for `sync`, `{ data, total, filtered }` for `query`, the record for `create` / `update`, and the
|
|
105
|
-
server response for `delete` / `bulk-delete`. `message` is the same opaque toast payload as the REST
|
|
106
|
-
`{ message, content }` envelope.
|
|
107
|
-
|
|
108
|
-
**Push** — no `ref`: `{ "type": "changes", "data": [...], "deleted": [...], "synced_at": … }`.
|
|
109
|
-
|
|
110
|
-
`synced_at` is the same token the REST delta takes as `since`. Beside REST, a push advances the
|
|
111
|
-
store's `lastSyncedAt`, and the next REST sync sends it — the server must keep both in one currency.
|
|
112
|
-
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
## Coordinator Integration
|
|
116
|
-
|
|
117
|
-
`ln-data-coordinator` needs no wiring:
|
|
118
|
-
|
|
119
|
-
- **Request connector:** `[data-ln-api-connector]` or `[data-ln-couchdb-connector]` when present,
|
|
120
|
-
otherwise `[data-ln-websocket-connector]`.
|
|
121
|
-
- **Pushes:** `:fetched` without `meta.kind` goes to `store.applySync` — upsert plus delete, the path
|
|
122
|
-
CouchDB sync already uses. Bound tables and lists refresh on `ln-data-store:synced`.
|
|
123
|
-
- **Catch-up:** on every `:connected` the coordinator runs `store.forceSync()`, a delta since
|
|
124
|
-
`lastSyncedAt`, over whichever connector takes requests.
|
|
125
|
-
|
|
126
|
-
### Showing the status
|
|
127
|
-
|
|
128
|
-
The coordinator does not render connection status. Page wiring listens and draws it — here with
|
|
129
|
-
an app-owned `data-status`, since app state stays out of `data-ln-*`:
|
|
130
|
-
|
|
131
|
-
```js
|
|
132
|
-
const chip = document.getElementById('tasks-status');
|
|
133
|
-
['connecting', 'connected', 'disconnected'].forEach(function (status) {
|
|
134
|
-
coordinatorEl.addEventListener('ln-websocket-connector:' + status, function () {
|
|
135
|
-
chip.setAttribute('data-status', status);
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
## 🔧 Internals
|
|
143
|
-
|
|
144
|
-
Source: `components/ln-websocket-connector/src/ln-websocket-connector.js`.
|
|
145
|
-
|
|
146
|
-
### Requests while not connected
|
|
147
|
-
|
|
148
|
-
- **Command `connect`, socket not open** (first connect, or between reconnect attempts): the request
|
|
149
|
-
is held and sent in order on open. `:connected` is dispatched before the flush, so the coordinator's
|
|
150
|
-
catch-up sync sees the store already syncing and does not send a second one.
|
|
151
|
-
- **Command `disconnect`:** the request fails at once with `:error { status: 0 }`.
|
|
152
|
-
- **Socket closes with replies outstanding:** each one fails with `:error { status: 0 }`. The
|
|
153
|
-
coordinator treats status 0 as transient and never deletes local data on it.
|
|
154
|
-
|
|
155
|
-
### Reconnect
|
|
156
|
-
|
|
157
|
-
An unexpected close while the command is `connect` retries after 1 s, doubling up to 30 s, and the
|
|
158
|
-
counter resets on a successful open. `new WebSocket()` throwing synchronously (an invalid URL, or
|
|
159
|
-
`ws://` blocked on an `https://` page) is not retried: retrying cannot fix it. The component reports
|
|
160
|
-
`:disconnected { willReconnect: false }`; a new URL or a new `connect` command opens again.
|
|
161
|
-
|
|
162
|
-
### Teardown
|
|
163
|
-
|
|
164
|
-
`destroy()` closes the socket, clears the reconnect timer, removes the request listeners and
|
|
165
|
-
deletes the instance. It dispatches nothing, so held and outstanding requests are discarded, not
|
|
166
|
-
failed.
|
|
1
|
+
# `data-ln-websocket-connector`
|
|
2
|
+
|
|
3
|
+
> Applied to an element inside a `ln-data-coordinator`. Opens a WebSocket, turns server pushes into
|
|
4
|
+
> `ln-websocket-connector:fetched`, and answers the same request events as `ln-api-connector` and
|
|
5
|
+
> `ln-couchdb-connector`. Connection status is private state announced by events — never an attribute.
|
|
6
|
+
|
|
7
|
+
A zero-dependency push transport. Beside a REST connector it only delivers live changes; on its own
|
|
8
|
+
it carries reads, writes and pushes over one socket.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Declarative DOM Setup
|
|
13
|
+
|
|
14
|
+
### Live changes beside REST
|
|
15
|
+
|
|
16
|
+
The REST connector takes every request; the socket only pushes changes into the store.
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<ul data-ln-data-coordinator="tasks" hidden>
|
|
20
|
+
<li data-ln-data-store="tasks" id="tasks"></li>
|
|
21
|
+
<li data-ln-api-connector data-ln-api-base-url="https://api.example.com" data-ln-api-path="tasks"></li>
|
|
22
|
+
<li data-ln-websocket-connector data-ln-websocket-connector-url="wss://api.example.com/live"></li>
|
|
23
|
+
</ul>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Socket alone
|
|
27
|
+
|
|
28
|
+
With no REST or CouchDB connector in the coordinator, the socket takes every request too.
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<ul data-ln-data-coordinator="tasks" hidden>
|
|
32
|
+
<li data-ln-data-store="tasks" id="tasks"></li>
|
|
33
|
+
<li data-ln-websocket-connector data-ln-websocket-connector-url="wss://api.example.com/live"></li>
|
|
34
|
+
</ul>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Attributes
|
|
40
|
+
|
|
41
|
+
Both attributes are commands set from outside; the component obeys them.
|
|
42
|
+
|
|
43
|
+
| Attribute | Values | Default | Description |
|
|
44
|
+
|-----------|--------|---------|-------------|
|
|
45
|
+
| `data-ln-websocket-connector` | `connect` \| `disconnect` | `connect` | Opens or closes the socket. A bare attribute connects. |
|
|
46
|
+
| `data-ln-websocket-connector-url` | `ws://…` \| `wss://…` | — | Endpoint. Changing it while connected closes and reopens on the new URL. |
|
|
47
|
+
|
|
48
|
+
There is no attribute for the connection status. `connecting`, `connected` and `disconnected` are
|
|
49
|
+
what the component observes, not something anyone can set — writing `connected` into an attribute
|
|
50
|
+
would not connect anything. The status is announced by events; whoever listens decides how to show it.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## DOM Events
|
|
55
|
+
|
|
56
|
+
### Commands (dispatched TO the connector)
|
|
57
|
+
|
|
58
|
+
Only the `ln-websocket-connector:*` namespace is handled.
|
|
59
|
+
|
|
60
|
+
| Event | `detail` | Description |
|
|
61
|
+
|-------|----------|-------------|
|
|
62
|
+
| `ln-websocket-connector:request-sync` | `{ since, meta? }` | Delta sync since a token. |
|
|
63
|
+
| `ln-websocket-connector:request-query` | `{ query, meta? }` | One page of a query (`search`, `filters`, `sort`, `offset`, `limit`). |
|
|
64
|
+
| `ln-websocket-connector:request-create` | `{ data, tempId?, idempotencyKey?, meta? }` | Create a record. |
|
|
65
|
+
| `ln-websocket-connector:request-update` | `{ id, data, expected_version?, idempotencyKey?, meta? }` | Update a record. |
|
|
66
|
+
| `ln-websocket-connector:request-delete` | `{ id, idempotencyKey?, meta? }` | Delete a record. |
|
|
67
|
+
| `ln-websocket-connector:request-bulk-delete` | `{ ids, idempotencyKey?, meta? }` | Delete several records. |
|
|
68
|
+
|
|
69
|
+
### Notifications (emitted BY the connector)
|
|
70
|
+
|
|
71
|
+
| Event | `detail` | Description |
|
|
72
|
+
|-------|----------|-------------|
|
|
73
|
+
| `ln-websocket-connector:connecting` | `{ url, attempt }` | A connection attempt starts. `attempt` counts from 1 and resets on open. |
|
|
74
|
+
| `ln-websocket-connector:connected` | `{ url }` | The socket is open. |
|
|
75
|
+
| `ln-websocket-connector:disconnected` | `{ url, code, reason, willReconnect }` | The socket closed, or a pending reconnect was cancelled. |
|
|
76
|
+
| `ln-websocket-connector:fetched` | `{ data, since, meta }` / `{ data, total, filtered, offset, queryGen, meta }` | A sync reply, a query page, or a server push (`meta: null`). |
|
|
77
|
+
| `ln-websocket-connector:created` | `{ record, tempId, message, meta }` | Create confirmed. |
|
|
78
|
+
| `ln-websocket-connector:updated` | `{ record, id, message, meta }` | Update confirmed. |
|
|
79
|
+
| `ln-websocket-connector:deleted` | `{ response, id, message, meta }` | Delete confirmed. |
|
|
80
|
+
| `ln-websocket-connector:bulk-deleted` | `{ response, ids, message, meta }` | Bulk delete confirmed. |
|
|
81
|
+
| `ln-websocket-connector:error` | `{ action, error, status, data, conflictData, meta, … }` | A rejected request, or one that could not be delivered (`status: 0`). |
|
|
82
|
+
|
|
83
|
+
`meta` is echoed unchanged and never leaves the page.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Wire Protocol
|
|
88
|
+
|
|
89
|
+
JSON text frames.
|
|
90
|
+
|
|
91
|
+
**Request** — `{ "ref": "<string>", "type": "<type>", ...payload }`
|
|
92
|
+
|
|
93
|
+
| `type` | payload |
|
|
94
|
+
|--------|---------|
|
|
95
|
+
| `sync` | `since` |
|
|
96
|
+
| `query` | `query` |
|
|
97
|
+
| `create` | `data`, `idempotencyKey` |
|
|
98
|
+
| `update` | `id`, `data`, `expected_version`, `idempotencyKey` |
|
|
99
|
+
| `delete` | `id`, `idempotencyKey` |
|
|
100
|
+
| `bulk-delete` | `ids`, `idempotencyKey` |
|
|
101
|
+
|
|
102
|
+
**Reply** — the same `ref`, then either `{ "ok": true, "content": …, "message": … }` or
|
|
103
|
+
`{ "ok": false, "status": 409, "error": "…", "data": … }`. `content` is `{ data, deleted, synced_at }`
|
|
104
|
+
for `sync`, `{ data, total, filtered }` for `query`, the record for `create` / `update`, and the
|
|
105
|
+
server response for `delete` / `bulk-delete`. `message` is the same opaque toast payload as the REST
|
|
106
|
+
`{ message, content }` envelope.
|
|
107
|
+
|
|
108
|
+
**Push** — no `ref`: `{ "type": "changes", "data": [...], "deleted": [...], "synced_at": … }`.
|
|
109
|
+
|
|
110
|
+
`synced_at` is the same token the REST delta takes as `since`. Beside REST, a push advances the
|
|
111
|
+
store's `lastSyncedAt`, and the next REST sync sends it — the server must keep both in one currency.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Coordinator Integration
|
|
116
|
+
|
|
117
|
+
`ln-data-coordinator` needs no wiring:
|
|
118
|
+
|
|
119
|
+
- **Request connector:** `[data-ln-api-connector]` or `[data-ln-couchdb-connector]` when present,
|
|
120
|
+
otherwise `[data-ln-websocket-connector]`.
|
|
121
|
+
- **Pushes:** `:fetched` without `meta.kind` goes to `store.applySync` — upsert plus delete, the path
|
|
122
|
+
CouchDB sync already uses. Bound tables and lists refresh on `ln-data-store:synced`.
|
|
123
|
+
- **Catch-up:** on every `:connected` the coordinator runs `store.forceSync()`, a delta since
|
|
124
|
+
`lastSyncedAt`, over whichever connector takes requests.
|
|
125
|
+
|
|
126
|
+
### Showing the status
|
|
127
|
+
|
|
128
|
+
The coordinator does not render connection status. Page wiring listens and draws it — here with
|
|
129
|
+
an app-owned `data-status`, since app state stays out of `data-ln-*`:
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
const chip = document.getElementById('tasks-status');
|
|
133
|
+
['connecting', 'connected', 'disconnected'].forEach(function (status) {
|
|
134
|
+
coordinatorEl.addEventListener('ln-websocket-connector:' + status, function () {
|
|
135
|
+
chip.setAttribute('data-status', status);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 🔧 Internals
|
|
143
|
+
|
|
144
|
+
Source: `components/ln-websocket-connector/src/ln-websocket-connector.js`.
|
|
145
|
+
|
|
146
|
+
### Requests while not connected
|
|
147
|
+
|
|
148
|
+
- **Command `connect`, socket not open** (first connect, or between reconnect attempts): the request
|
|
149
|
+
is held and sent in order on open. `:connected` is dispatched before the flush, so the coordinator's
|
|
150
|
+
catch-up sync sees the store already syncing and does not send a second one.
|
|
151
|
+
- **Command `disconnect`:** the request fails at once with `:error { status: 0 }`.
|
|
152
|
+
- **Socket closes with replies outstanding:** each one fails with `:error { status: 0 }`. The
|
|
153
|
+
coordinator treats status 0 as transient and never deletes local data on it.
|
|
154
|
+
|
|
155
|
+
### Reconnect
|
|
156
|
+
|
|
157
|
+
An unexpected close while the command is `connect` retries after 1 s, doubling up to 30 s, and the
|
|
158
|
+
counter resets on a successful open. `new WebSocket()` throwing synchronously (an invalid URL, or
|
|
159
|
+
`ws://` blocked on an `https://` page) is not retried: retrying cannot fix it. The component reports
|
|
160
|
+
`:disconnected { willReconnect: false }`; a new URL or a new `connect` command opens again.
|
|
161
|
+
|
|
162
|
+
### Teardown
|
|
163
|
+
|
|
164
|
+
`destroy()` closes the socket, clears the reconnect timer, removes the request listeners and
|
|
165
|
+
deletes the instance. It dispatches nothing, so held and outstanding requests are discarded, not
|
|
166
|
+
failed.
|