@livenetworks/ashlar 1.6.1 → 2.0.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/LICENSE +641 -0
- package/README.md +202 -86
- package/{js → components}/COMPONENTS.md +1116 -1108
- package/{js → components}/index.js +81 -58
- package/{js → components}/ln-accordion/README.md +7 -6
- package/components/ln-accordion/ln-accordion-dev.scss +8 -0
- package/components/ln-accordion/ln-accordion.js +1 -0
- package/components/ln-accordion/ln-accordion.schema.json +30 -0
- package/components/ln-accordion/ln-accordion.scss +8 -0
- package/{js → components}/ln-accordion/src/ln-accordion.js +8 -2
- package/{js → components}/ln-ajax/README.md +171 -160
- package/components/ln-ajax/ln-ajax-dev.scss +8 -0
- package/components/ln-ajax/ln-ajax.js +1 -0
- package/components/ln-ajax/ln-ajax.schema.json +30 -0
- package/{js → components}/ln-ajax/src/ln-ajax.js +65 -30
- package/{js → components}/ln-api-connector/README.md +27 -5
- package/components/ln-api-connector/ln-api-connector.js +1 -0
- package/components/ln-api-connector/ln-api-connector.schema.json +96 -0
- package/components/ln-api-connector/src/connector-core.js +97 -0
- package/components/ln-api-connector/src/ln-api-connector.js +447 -0
- package/{js → components}/ln-api-queue/README.md +12 -9
- package/components/ln-api-queue/ln-api-queue.js +1 -0
- package/components/ln-api-queue/ln-api-queue.schema.json +34 -0
- package/{js → components}/ln-api-queue/src/ln-api-queue.js +33 -14
- package/{js → components}/ln-api-queue/src/queue-storage.js +7 -3
- package/{js → components}/ln-autoresize/README.md +129 -127
- package/components/ln-autoresize/ln-autoresize-dev.scss +8 -0
- package/components/ln-autoresize/ln-autoresize.js +1 -0
- package/components/ln-autoresize/ln-autoresize.schema.json +22 -0
- package/{js → components}/ln-autoresize/src/ln-autoresize.js +8 -1
- package/{js → components}/ln-autosave/README.md +127 -124
- package/components/ln-autosave/ln-autosave-dev.scss +13 -0
- package/components/ln-autosave/ln-autosave.js +1 -0
- package/components/ln-autosave/ln-autosave.schema.json +48 -0
- package/components/ln-autosave/src/autosave-model.js +34 -0
- package/{js → components}/ln-autosave/src/ln-autosave.js +65 -58
- package/components/ln-chart/README.md +145 -0
- package/components/ln-chart/ln-chart-dev.scss +20 -0
- package/components/ln-chart/ln-chart.js +1 -0
- package/components/ln-chart/ln-chart.schema.json +146 -0
- package/components/ln-chart/ln-chart.scss +8 -0
- package/components/ln-chart/src/chart-model.js +154 -0
- package/components/ln-chart/src/ln-chart.js +176 -0
- package/{js → components}/ln-circular-progress/README.md +15 -14
- package/components/ln-circular-progress/ln-circular-progress-dev.scss +8 -0
- package/components/ln-circular-progress/ln-circular-progress.js +1 -0
- package/components/ln-circular-progress/ln-circular-progress.schema.json +42 -0
- package/{js → components}/ln-circular-progress/src/ln-circular-progress.js +32 -50
- package/{js → components}/ln-confirm/README.md +69 -18
- package/components/ln-confirm/ln-confirm-dev.scss +24 -0
- package/components/ln-confirm/ln-confirm.js +1 -0
- package/components/ln-confirm/ln-confirm.schema.json +66 -0
- package/components/ln-confirm/ln-confirm.scss +24 -0
- package/{js → components}/ln-confirm/src/ln-confirm.js +180 -171
- package/{js → components}/ln-core/README.md +374 -149
- package/components/ln-core/attrs.js +273 -0
- package/components/ln-core/compare.js +40 -0
- package/components/ln-core/crypto.js +265 -0
- package/components/ln-core/date.js +50 -0
- package/components/ln-core/dom.js +115 -0
- package/components/ln-core/events.js +122 -0
- package/components/ln-core/form.js +136 -0
- package/{js → components}/ln-core/hash.js +149 -92
- package/components/ln-core/helpers.js +33 -0
- package/components/ln-core/http.js +48 -0
- package/components/ln-core/index.js +11 -0
- package/components/ln-core/lifecycle.js +403 -0
- package/components/ln-core/ln-core.schema.json +109 -0
- package/components/ln-core/locale.js +55 -0
- package/components/ln-core/matching.js +78 -0
- package/components/ln-core/number.js +125 -0
- package/components/ln-core/progress.js +30 -0
- package/components/ln-core/template.js +206 -0
- package/{js → components}/ln-core/window-cache.js +247 -213
- package/{js → components}/ln-couchdb-connector/README.md +7 -5
- package/components/ln-couchdb-connector/ln-couchdb-connector.js +1 -0
- package/components/ln-couchdb-connector/ln-couchdb-connector.schema.json +50 -0
- package/{js → components}/ln-couchdb-connector/src/ln-couchdb-connector.js +29 -43
- package/{js → components}/ln-data-coordinator/README.md +109 -73
- package/components/ln-data-coordinator/ln-data-coordinator-dev.scss +8 -0
- package/components/ln-data-coordinator/ln-data-coordinator.js +1 -0
- package/components/ln-data-coordinator/ln-data-coordinator.schema.json +196 -0
- package/components/ln-data-coordinator/src/data-read-policy.js +41 -0
- package/{js → components}/ln-data-coordinator/src/ln-data-coordinator.js +411 -154
- package/{js → components}/ln-data-coordinator/src/mutation-receipts.js +0 -5
- package/{js → components}/ln-data-store/README.md +42 -17
- package/components/ln-data-store/ln-data-store-dev.scss +13 -0
- package/components/ln-data-store/ln-data-store.js +1 -0
- package/components/ln-data-store/ln-data-store.schema.json +84 -0
- package/components/ln-data-store/src/data-store-model.js +155 -0
- package/{js → components}/ln-data-store/src/ln-data-store.js +407 -105
- package/components/ln-data-store/src/window-index.js +119 -0
- package/{js → components}/ln-date/README.md +17 -7
- package/{js → components}/ln-date/ln-date-dev.scss +14 -14
- package/components/ln-date/ln-date.js +1 -0
- package/components/ln-date/ln-date.schema.json +92 -0
- package/components/ln-date/src/date-model.js +186 -0
- package/components/ln-date/src/ln-date.js +486 -0
- package/components/ln-debug/README.md +132 -0
- package/components/ln-debug/ln-debug.js +1 -0
- package/components/ln-debug/ln-debug.schema.json +28 -0
- package/components/ln-debug/src/console-sink.js +19 -0
- package/components/ln-debug/src/debug-verifier.js +331 -0
- package/components/ln-debug/src/gate.js +95 -0
- package/components/ln-debug/src/generated-attributes.js +299 -0
- package/components/ln-debug/src/ln-debug.js +60 -0
- package/{js → components}/ln-dropdown/README.md +150 -140
- package/components/ln-dropdown/ln-dropdown-dev.scss +13 -0
- package/components/ln-dropdown/ln-dropdown.js +1 -0
- package/components/ln-dropdown/ln-dropdown.schema.json +90 -0
- package/components/ln-dropdown/ln-dropdown.scss +18 -0
- package/{js → components}/ln-dropdown/src/ln-dropdown.js +114 -11
- package/{js → components}/ln-editor/README.md +11 -9
- package/components/ln-editor/ln-editor-dev.scss +18 -0
- package/components/ln-editor/ln-editor.js +1 -0
- package/components/ln-editor/ln-editor.schema.json +58 -0
- package/components/ln-editor/ln-editor.scss +13 -0
- package/{js → components}/ln-editor/src/ln-editor.js +59 -11
- package/{js → components}/ln-external-links/README.md +10 -8
- package/components/ln-external-links/ln-external-links.js +1 -0
- package/components/ln-external-links/ln-external-links.schema.json +18 -0
- package/{js → components}/ln-external-links/src/ln-external-links.js +13 -11
- package/{js → components}/ln-fill/README.md +6 -8
- package/components/ln-fill/ln-fill.js +1 -0
- package/components/ln-fill/ln-fill.schema.json +23 -0
- package/{js → components}/ln-fill/src/ln-fill.js +7 -1
- package/components/ln-filter/README.md +131 -0
- package/components/ln-filter/ln-filter-dev.scss +13 -0
- package/components/ln-filter/ln-filter.js +1 -0
- package/components/ln-filter/ln-filter.schema.json +153 -0
- package/components/ln-filter/src/filter-model.js +185 -0
- package/components/ln-filter/src/ln-filter.js +435 -0
- package/{js → components}/ln-form/README.md +260 -264
- package/components/ln-form/ln-form-dev.scss +8 -0
- package/components/ln-form/ln-form.js +1 -0
- package/components/ln-form/ln-form.schema.json +45 -0
- package/{js → components}/ln-form/src/ln-form.js +107 -99
- package/{js → components}/ln-http/README.md +11 -6
- package/components/ln-http/ln-http.js +1 -0
- package/components/ln-http/ln-http.schema.json +6 -0
- package/components/ln-http/src/http-core.js +51 -0
- package/{js → components}/ln-http/src/ln-http.js +28 -33
- package/{js → components}/ln-icon/README.md +16 -9
- package/components/ln-icon/ln-icon.schema.json +6 -0
- package/components/ln-include/README.md +75 -0
- package/components/ln-include/ln-include-dev.scss +13 -0
- package/components/ln-include/ln-include.js +1 -0
- package/components/ln-include/ln-include.schema.json +23 -0
- package/components/ln-include/src/ln-include.js +111 -0
- package/components/ln-key/README.md +130 -0
- package/components/ln-key/ln-key-dev.scss +18 -0
- package/components/ln-key/ln-key.js +1 -0
- package/components/ln-key/ln-key.schema.json +56 -0
- package/components/ln-key/src/key-model.js +146 -0
- package/components/ln-key/src/ln-key.js +201 -0
- package/{js → components}/ln-link/README.md +7 -9
- package/components/ln-link/ln-link-dev.scss +8 -0
- package/components/ln-link/ln-link.js +1 -0
- package/components/ln-link/ln-link.schema.json +22 -0
- package/{js → components}/ln-link/src/ln-link.js +16 -11
- package/components/ln-list/README.md +152 -0
- package/components/ln-list/ln-list-dev.scss +8 -0
- package/components/ln-list/ln-list.js +1 -0
- package/components/ln-list/ln-list.schema.json +166 -0
- package/components/ln-list/ln-list.scss +25 -0
- package/{js → components}/ln-list/src/ln-list.js +1301 -1216
- package/{js → components}/ln-modal/README.md +13 -10
- package/components/ln-modal/ln-modal-dev.scss +18 -0
- package/components/ln-modal/ln-modal.js +1 -0
- package/components/ln-modal/ln-modal.schema.json +54 -0
- package/components/ln-modal/ln-modal.scss +51 -0
- package/{js → components}/ln-modal/src/ln-modal.js +164 -137
- package/{js → components}/ln-nav/README.md +11 -11
- package/components/ln-nav/ln-nav.js +1 -0
- package/components/ln-nav/ln-nav.schema.json +25 -0
- package/{js → components}/ln-nav/src/ln-nav.js +25 -14
- package/components/ln-number/README.md +205 -0
- package/{js → components}/ln-number/ln-number-dev.scss +13 -13
- package/components/ln-number/ln-number.js +1 -0
- package/components/ln-number/ln-number.schema.json +63 -0
- package/components/ln-number/src/ln-number.js +400 -0
- package/components/ln-number/src/number-model.js +31 -0
- package/components/ln-obfuscator/README.md +60 -0
- package/components/ln-obfuscator/ln-obfuscator.js +1 -0
- package/components/ln-obfuscator/ln-obfuscator.schema.json +49 -0
- package/components/ln-obfuscator/src/ln-obfuscator.js +159 -0
- package/components/ln-obfuscator/src/obfuscator-model.js +250 -0
- package/{js → components}/ln-options/README.md +3 -1
- package/components/ln-options/ln-options-dev.scss +13 -0
- package/components/ln-options/ln-options.js +1 -0
- package/components/ln-options/ln-options.schema.json +41 -0
- package/{js → components}/ln-options/src/ln-options.js +13 -5
- package/components/ln-persist/README.md +151 -0
- package/components/ln-persist/ln-persist.js +1 -0
- package/components/ln-persist/ln-persist.schema.json +28 -0
- package/components/ln-persist/src/ln-persist.js +83 -0
- package/components/ln-picklist/README.md +230 -0
- package/components/ln-picklist/ln-picklist-dev.scss +22 -0
- package/components/ln-picklist/ln-picklist.js +1 -0
- package/components/ln-picklist/ln-picklist.schema.json +49 -0
- package/components/ln-picklist/src/ln-picklist.js +228 -0
- package/{js → components}/ln-popover/README.md +164 -162
- package/components/ln-popover/ln-popover-dev.scss +13 -0
- package/components/ln-popover/ln-popover.js +1 -0
- package/components/ln-popover/ln-popover.schema.json +82 -0
- package/components/ln-popover/ln-popover.scss +18 -0
- package/{js → components}/ln-popover/src/ln-popover.js +42 -36
- package/{js → components}/ln-progress/README.md +410 -413
- package/components/ln-progress/ln-progress-dev.scss +8 -0
- package/components/ln-progress/ln-progress.js +1 -0
- package/components/ln-progress/ln-progress.schema.json +40 -0
- package/components/ln-progress/src/ln-progress.js +91 -0
- package/components/ln-progress/src/progress-model.js +20 -0
- package/{js → components}/ln-router/README.md +443 -432
- package/components/ln-router/ln-router-dev.scss +13 -0
- package/components/ln-router/ln-router.js +1 -0
- package/components/ln-router/ln-router.schema.json +68 -0
- package/{js → components}/ln-router/src/ln-router.js +585 -539
- package/components/ln-router/src/router-model.js +50 -0
- package/components/ln-scroll/README.md +45 -0
- package/components/ln-scroll/ln-scroll.js +1 -0
- package/components/ln-scroll/ln-scroll.schema.json +85 -0
- package/components/ln-scroll/src/ln-scroll.js +150 -0
- package/components/ln-search/README.md +188 -0
- package/components/ln-search/ln-search-dev.scss +13 -0
- package/components/ln-search/ln-search.js +1 -0
- package/components/ln-search/ln-search.schema.json +103 -0
- package/components/ln-search/src/ln-search.js +330 -0
- package/{js → components}/ln-slug/README.md +6 -3
- package/components/ln-slug/ln-slug-dev.scss +18 -0
- package/components/ln-slug/ln-slug.js +1 -0
- package/components/ln-slug/ln-slug.schema.json +23 -0
- package/{js → components}/ln-slug/src/ln-slug.js +20 -13
- package/components/ln-slug/src/slug-model.js +21 -0
- package/{js → components}/ln-sort/README.md +178 -170
- package/{js → components}/ln-sort/ln-sort-dev.scss +8 -8
- package/components/ln-sort/ln-sort.js +1 -0
- package/components/ln-sort/ln-sort.schema.json +104 -0
- package/components/ln-sort/src/ln-sort.js +321 -0
- package/components/ln-sort/src/sort-model.js +117 -0
- package/{js → components}/ln-sortable/README.md +7 -11
- package/components/ln-sortable/ln-sortable-dev.scss +13 -0
- package/components/ln-sortable/ln-sortable.js +1 -0
- package/components/ln-sortable/ln-sortable.schema.json +36 -0
- package/{js → components}/ln-sortable/src/ln-sortable.js +8 -13
- package/{js → components}/ln-stat/README.md +3 -1
- package/components/ln-stat/ln-stat-dev.scss +8 -0
- package/components/ln-stat/ln-stat.js +1 -0
- package/components/ln-stat/ln-stat.schema.json +32 -0
- package/{js → components}/ln-stat/src/ln-stat.js +14 -18
- package/components/ln-stat/src/stat-model.js +28 -0
- package/{js → components}/ln-table/README.md +37 -24
- package/{js → components}/ln-table/ln-table-dev.scss +17 -17
- package/components/ln-table/ln-table.js +1 -0
- package/components/ln-table/ln-table.schema.json +211 -0
- package/components/ln-table/ln-table.scss +15 -0
- package/{js → components}/ln-table/src/ln-table.js +1365 -1493
- package/components/ln-table/src/table-model.js +98 -0
- package/components/ln-table-coordinator/README.md +61 -0
- package/components/ln-table-coordinator/ln-table-coordinator.js +1 -0
- package/components/ln-table-coordinator/ln-table-coordinator.schema.json +93 -0
- package/components/ln-table-coordinator/src/ln-table-coordinator.js +193 -0
- package/{js → components}/ln-tabs/README.md +32 -14
- package/components/ln-tabs/ln-tabs-dev.scss +24 -0
- package/components/ln-tabs/ln-tabs.js +1 -0
- package/components/ln-tabs/ln-tabs.schema.json +75 -0
- package/components/ln-tabs/ln-tabs.scss +8 -0
- package/components/ln-tabs/src/ln-tabs.js +207 -0
- package/components/ln-tabs/src/tabs-model.js +82 -0
- package/{js → components}/ln-time/README.md +96 -95
- package/components/ln-time/ln-time-dev.scss +13 -0
- package/components/ln-time/ln-time.js +1 -0
- package/components/ln-time/ln-time.schema.json +38 -0
- package/{js → components}/ln-time/src/ln-time.js +206 -223
- package/components/ln-time/src/time-model.js +64 -0
- package/{js → components}/ln-toast/README.md +23 -5
- package/components/ln-toast/ln-toast-dev.scss +8 -0
- package/components/ln-toast/ln-toast.js +1 -0
- package/components/ln-toast/ln-toast.schema.json +65 -0
- package/components/ln-toast/ln-toast.scss +59 -0
- package/{js → components}/ln-toast/src/ln-toast.js +233 -232
- package/{js → components}/ln-toggle/README.md +198 -196
- package/{js → components}/ln-toggle/ln-toggle-dev.scss +13 -13
- package/components/ln-toggle/ln-toggle.js +1 -0
- package/components/ln-toggle/ln-toggle.schema.json +52 -0
- package/components/ln-toggle/ln-toggle.scss +37 -0
- package/{js → components}/ln-toggle/src/ln-toggle.js +61 -46
- package/{js → components}/ln-tooltip/README.md +6 -6
- package/{js → components}/ln-tooltip/ln-tooltip-dev.scss +9 -9
- package/components/ln-tooltip/ln-tooltip.js +1 -0
- package/components/ln-tooltip/ln-tooltip.schema.json +86 -0
- package/components/ln-tooltip/ln-tooltip.scss +9 -0
- package/{js → components}/ln-tooltip/src/ln-tooltip.js +14 -3
- package/{js → components}/ln-translations/README.md +3 -1
- package/components/ln-translations/ln-translations-dev.scss +13 -0
- package/components/ln-translations/ln-translations.js +1 -0
- package/components/ln-translations/ln-translations.schema.json +120 -0
- package/{js → components}/ln-translations/src/ln-translations.js +25 -10
- package/components/ln-ui-coordinator/README.md +101 -0
- package/components/ln-ui-coordinator/ln-ui-coordinator-dev.scss +8 -0
- package/components/ln-ui-coordinator/ln-ui-coordinator.js +1 -0
- package/components/ln-ui-coordinator/ln-ui-coordinator.schema.json +60 -0
- package/{js/ln-modal-coordinator/src/ln-modal-coordinator.js → components/ln-ui-coordinator/src/ln-ui-coordinator.js} +403 -345
- package/components/ln-upload/README.md +133 -0
- package/components/ln-upload/ln-upload-dev.scss +18 -0
- package/components/ln-upload/ln-upload.js +1 -0
- package/components/ln-upload/ln-upload.schema.json +193 -0
- package/components/ln-upload/ln-upload.scss +20 -0
- package/components/ln-upload/src/ln-upload.js +652 -0
- package/components/ln-upload/src/upload-model.js +78 -0
- package/{js → components}/ln-validate/README.md +182 -180
- package/{js → components}/ln-validate/ln-validate-dev.scss +15 -15
- package/components/ln-validate/ln-validate.js +1 -0
- package/components/ln-validate/ln-validate.schema.json +50 -0
- package/components/ln-validate/ln-validate.scss +7 -0
- package/{js → components}/ln-validate/src/ln-validate.js +23 -45
- package/components/ln-validate/src/validate-model.js +64 -0
- package/components/ln-websocket-connector/README.md +166 -0
- package/components/ln-websocket-connector/ln-websocket-connector.js +1 -0
- package/components/ln-websocket-connector/ln-websocket-connector.schema.json +29 -0
- package/components/ln-websocket-connector/src/ln-websocket-connector.js +279 -0
- package/ln-ashlar.html-data.json +1796 -0
- package/package.json +84 -61
- package/{scss → theme}/base/_global.scss +1 -2
- package/{scss → theme}/base/_reset.scss +1 -1
- package/{scss → theme}/base/_typography.scss +2 -0
- package/theme/brand.css +73 -0
- package/{scss → theme}/components/_app-shell.scss +8 -0
- package/theme/components/_button.scss +24 -0
- package/theme/components/_chart.scss +5 -0
- package/theme/components/_confirm.scss +6 -0
- package/{scss → theme}/components/_date.scss +30 -22
- package/{scss → theme}/components/_dropdown.scss +6 -1
- package/theme/components/_form.scss +140 -0
- package/{scss → theme}/components/_layout.scss +6 -0
- package/{scss → theme}/components/_ln-table.scss +1 -6
- package/theme/components/_picklist.scss +3 -0
- package/{scss → theme}/components/_sort.scss +10 -10
- package/theme/components/_status-badge.scss +6 -0
- package/{scss → theme}/components/_table.scss +16 -0
- package/{scss → theme}/components/_tabs.scss +0 -4
- package/theme/components/_toast.scss +48 -0
- package/{scss → theme}/components/_toggle.scss +1 -1
- package/theme/components/_upload.scss +45 -0
- package/{scss → theme}/config/_breakpoints.scss +1 -1
- package/theme/config/_contrast.scss +128 -0
- package/{scss → theme}/config/_density.scss +191 -205
- package/theme/config/_palette.scss +274 -0
- package/theme/config/_theme.scss +293 -0
- package/{scss → theme}/config/_tokens.scss +285 -441
- package/{scss → theme}/config/mixins/_accordion.scss +1 -1
- package/{scss → theme}/config/mixins/_alert.scss +1 -0
- package/{scss → theme}/config/mixins/_app-shell.scss +4 -2
- package/{scss → theme}/config/mixins/_borders.scss +2 -0
- package/theme/config/mixins/_btn.scss +175 -0
- package/{scss → theme}/config/mixins/_card.scss +55 -46
- package/theme/config/mixins/_chart.scss +82 -0
- package/{scss → theme}/config/mixins/_collapsible.scss +2 -1
- package/{scss → theme}/config/mixins/_colors.scss +8 -14
- package/{scss → theme}/config/mixins/_diagnostics.scss +48 -48
- package/theme/config/mixins/_dropdown.scss +169 -0
- package/{scss → theme}/config/mixins/_editor.scss +0 -7
- package/{scss → theme}/config/mixins/_filter.scss +47 -47
- package/{scss → theme}/config/mixins/_footer.scss +1 -1
- package/{scss → theme}/config/mixins/_form.scss +49 -18
- package/{scss → theme}/config/mixins/_index.scss +62 -61
- package/{scss → theme}/config/mixins/_layout.scss +6 -2
- package/{scss → theme}/config/mixins/_ln-table.scss +31 -10
- package/{scss → theme}/config/mixins/_loader.scss +1 -1
- package/{scss → theme}/config/mixins/_modal.scss +145 -149
- package/{scss → theme}/config/mixins/_motion.scss +13 -0
- package/{scss → theme}/config/mixins/_nav.scss +7 -7
- package/theme/config/mixins/_picklist.scss +66 -0
- package/theme/config/mixins/_popover.scss +96 -0
- package/{scss → theme}/config/mixins/_sidebar.scss +7 -4
- package/{scss → theme}/config/mixins/_sort.scss +43 -42
- package/{scss → theme}/config/mixins/_status-badge.scss +15 -2
- package/{scss → theme}/config/mixins/_table.scss +25 -14
- package/{scss → theme}/config/mixins/_tabs.scss +1 -1
- package/{scss → theme}/config/mixins/_toast.scss +174 -179
- package/{scss → theme}/config/mixins/_tooltip.scss +2 -2
- package/{scss → theme}/config/mixins/_typography.scss +16 -5
- package/{scss → theme}/config/mixins/_upload.scss +8 -6
- package/theme/ln-ashlar-core.scss +24 -0
- package/theme/ln-ashlar-dev.scss +66 -0
- package/theme/ln-ashlar-landing.scss +56 -0
- package/{scss/ln-ashlar.scss → theme/ln-ashlar-theme.scss} +63 -69
- package/theme/ln-ashlar.scss +8 -0
- package/theme/presentation/_bento.scss +151 -0
- package/theme/presentation/_cta.scss +111 -0
- package/theme/presentation/_effects.scss +216 -0
- package/theme/presentation/_features.scss +108 -0
- package/theme/presentation/_footer.scss +129 -0
- package/theme/presentation/_hero.scss +158 -0
- package/theme/presentation/_layout.scss +170 -0
- package/theme/presentation/_navbar.scss +140 -0
- package/theme/presentation/_pricing.scss +262 -0
- package/theme/presentation/_stats.scss +87 -0
- package/theme/presentation/_testimonials.scss +124 -0
- package/theme/presentation/_tokens.scss +39 -0
- package/theme/presentation/_typography.scss +163 -0
- package/{scss → theme}/utilities/_animations.scss +38 -0
- package/{scss → theme}/utilities/_utilities.scss +6 -0
- package/web-types.json +2312 -0
- package/js/ln-accordion/ln-accordion.js +0 -1
- package/js/ln-ajax/ln-ajax.js +0 -1
- package/js/ln-api-connector/ln-api-connector.js +0 -1
- package/js/ln-api-connector/src/ln-api-connector.js +0 -368
- package/js/ln-api-queue/ln-api-queue.js +0 -1
- package/js/ln-autoresize/ln-autoresize.js +0 -1
- package/js/ln-autosave/ln-autosave.js +0 -1
- package/js/ln-circular-progress/ln-circular-progress.js +0 -1
- package/js/ln-confirm/_ln-confirm.scss +0 -24
- package/js/ln-confirm/ln-confirm.js +0 -1
- package/js/ln-core/crypto.js +0 -83
- package/js/ln-core/helpers.js +0 -788
- package/js/ln-core/index.js +0 -7
- package/js/ln-core/persist.js +0 -97
- package/js/ln-couchdb-connector/ln-couchdb-connector.js +0 -1
- package/js/ln-data-coordinator/ln-data-coordinator.js +0 -1
- package/js/ln-data-coordinator/src/data-read-policy.js +0 -18
- package/js/ln-data-store/ln-data-store.js +0 -1
- package/js/ln-date/ln-date.js +0 -1
- package/js/ln-date/src/ln-date.js +0 -603
- package/js/ln-debug/README.md +0 -58
- package/js/ln-debug/ln-debug.js +0 -1
- package/js/ln-debug/src/ln-debug.js +0 -19
- package/js/ln-dropdown/ln-dropdown.js +0 -1
- package/js/ln-dropdown/ln-dropdown.scss +0 -15
- package/js/ln-editor/ln-editor.js +0 -1
- package/js/ln-editor/ln-editor.scss +0 -43
- package/js/ln-external-links/ln-external-links.js +0 -1
- package/js/ln-fill/ln-fill.js +0 -1
- package/js/ln-filter/README.md +0 -189
- package/js/ln-filter/ln-filter-dev.scss +0 -8
- package/js/ln-filter/ln-filter.js +0 -1
- package/js/ln-filter/src/ln-filter.js +0 -419
- package/js/ln-form/ln-form.js +0 -1
- package/js/ln-http/ln-http.js +0 -1
- package/js/ln-link/ln-link.js +0 -1
- package/js/ln-list/README.md +0 -129
- package/js/ln-list/ln-list.js +0 -1
- package/js/ln-list/ln-list.scss +0 -28
- package/js/ln-modal/ln-modal-dev.scss +0 -13
- package/js/ln-modal/ln-modal.js +0 -1
- package/js/ln-modal/ln-modal.scss +0 -35
- package/js/ln-modal-coordinator/README.md +0 -99
- package/js/ln-modal-coordinator/ln-modal-coordinator-dev.scss +0 -8
- package/js/ln-modal-coordinator/ln-modal-coordinator.js +0 -1
- package/js/ln-nav/ln-nav.js +0 -1
- package/js/ln-number/README.md +0 -149
- package/js/ln-number/ln-number.js +0 -1
- package/js/ln-number/src/ln-number.js +0 -443
- package/js/ln-options/ln-options.js +0 -1
- package/js/ln-popover/ln-popover.js +0 -1
- package/js/ln-progress/ln-progress.js +0 -1
- package/js/ln-progress/src/ln-progress.js +0 -98
- package/js/ln-router/ln-router.js +0 -1
- package/js/ln-search/README.md +0 -158
- package/js/ln-search/ln-search-dev.scss +0 -8
- package/js/ln-search/ln-search.js +0 -1
- package/js/ln-search/src/ln-search.js +0 -117
- package/js/ln-slug/ln-slug.js +0 -1
- package/js/ln-sort/ln-sort.js +0 -1
- package/js/ln-sort/src/ln-sort.js +0 -178
- package/js/ln-sortable/ln-sortable.js +0 -1
- package/js/ln-stat/ln-stat.js +0 -1
- package/js/ln-table/ln-table.js +0 -1
- package/js/ln-table/ln-table.scss +0 -11
- package/js/ln-table-coordinator/README.md +0 -73
- package/js/ln-table-coordinator/ln-table-coordinator.js +0 -1
- package/js/ln-table-coordinator/src/ln-table-coordinator.js +0 -160
- package/js/ln-tabs/ln-tabs-dev.scss +0 -18
- package/js/ln-tabs/ln-tabs.js +0 -1
- package/js/ln-tabs/src/ln-tabs.js +0 -188
- package/js/ln-time/ln-time.js +0 -1
- package/js/ln-toast/ln-toast.js +0 -1
- package/js/ln-toggle/ln-toggle.js +0 -1
- package/js/ln-tooltip/ln-tooltip.js +0 -1
- package/js/ln-tooltip/ln-tooltip.scss +0 -9
- package/js/ln-translations/ln-translations.js +0 -1
- package/js/ln-upload/README.md +0 -255
- package/js/ln-upload/ln-upload.js +0 -1
- package/js/ln-upload/ln-upload.scss +0 -20
- package/js/ln-upload/src/ln-upload.js +0 -423
- package/js/ln-validate/ln-validate.js +0 -1
- package/scss/components/_button.scss +0 -20
- package/scss/components/_confirm.scss +0 -5
- package/scss/components/_form.scss +0 -107
- package/scss/components/_status-badge.scss +0 -4
- package/scss/components/_toast.scss +0 -68
- package/scss/components/_upload.scss +0 -51
- package/scss/config/_theme.scss +0 -216
- package/scss/config/mixins/_btn.scss +0 -179
- package/scss/config/mixins/_confirm.scss +0 -31
- package/scss/config/mixins/_dropdown.scss +0 -141
- package/scss/config/mixins/_popover.scss +0 -64
- package/scss/ln-ashlar-dev.scss +0 -39
- /package/{js → components}/ln-core/positioning.js +0 -0
- /package/{js → components}/ln-core/reactive.js +0 -0
- /package/{js → components}/ln-filter/ln-filter.scss +0 -0
- /package/{js → components}/ln-icon/ln-icon.js +0 -0
- /package/{js → components}/ln-icon/src/ln-icon.js +0 -0
- /package/{js → components}/ln-search/ln-search.scss +0 -0
- /package/{js → components}/ln-toast/template.html +0 -0
- /package/{scss → theme}/components/_accordion.scss +0 -0
- /package/{scss → theme}/components/_ajax.scss +0 -0
- /package/{scss → theme}/components/_alert.scss +0 -0
- /package/{scss → theme}/components/_avatar.scss +0 -0
- /package/{scss → theme}/components/_breadcrumbs.scss +0 -0
- /package/{scss → theme}/components/_card.scss +0 -0
- /package/{scss → theme}/components/_chip.scss +0 -0
- /package/{scss → theme}/components/_circular-progress.scss +0 -0
- /package/{scss → theme}/components/_editor.scss +0 -0
- /package/{scss → theme}/components/_empty-state.scss +0 -0
- /package/{scss → theme}/components/_filter.scss +0 -0
- /package/{scss → theme}/components/_link.scss +0 -0
- /package/{scss → theme}/components/_loader.scss +0 -0
- /package/{scss → theme}/components/_modal.scss +0 -0
- /package/{scss → theme}/components/_nav.scss +0 -0
- /package/{scss → theme}/components/_page-header.scss +0 -0
- /package/{scss → theme}/components/_popover.scss +0 -0
- /package/{scss → theme}/components/_progress.scss +0 -0
- /package/{scss → theme}/components/_prose.scss +0 -0
- /package/{scss → theme}/components/_scrollbar.scss +0 -0
- /package/{scss → theme}/components/_sections.scss +0 -0
- /package/{scss → theme}/components/_sidebar.scss +0 -0
- /package/{scss → theme}/components/_stat-card.scss +0 -0
- /package/{scss → theme}/components/_stepper.scss +0 -0
- /package/{scss → theme}/components/_timeline.scss +0 -0
- /package/{scss → theme}/components/_tooltip.scss +0 -0
- /package/{scss → theme}/components/_translations.scss +0 -0
- /package/{scss → theme}/config/_icons.scss +0 -0
- /package/{scss → theme}/config/_mixins.scss +0 -0
- /package/{scss → theme}/config/mixins/_ajax.scss +0 -0
- /package/{scss → theme}/config/mixins/_avatar.scss +0 -0
- /package/{scss → theme}/config/mixins/_breadcrumbs.scss +0 -0
- /package/{scss → theme}/config/mixins/_breakpoints.scss +0 -0
- /package/{scss → theme}/config/mixins/_chip.scss +0 -0
- /package/{scss → theme}/config/mixins/_circular-progress.scss +0 -0
- /package/{scss → theme}/config/mixins/_display.scss +0 -0
- /package/{scss → theme}/config/mixins/_empty-state.scss +0 -0
- /package/{scss → theme}/config/mixins/_focus.scss +0 -0
- /package/{scss → theme}/config/mixins/_interaction.scss +0 -0
- /package/{scss → theme}/config/mixins/_kbd.scss +0 -0
- /package/{scss → theme}/config/mixins/_link.scss +0 -0
- /package/{scss → theme}/config/mixins/_page-header.scss +0 -0
- /package/{scss → theme}/config/mixins/_position.scss +0 -0
- /package/{scss → theme}/config/mixins/_progress.scss +0 -0
- /package/{scss → theme}/config/mixins/_prose.scss +0 -0
- /package/{scss → theme}/config/mixins/_shadows.scss +0 -0
- /package/{scss → theme}/config/mixins/_sizing.scss +0 -0
- /package/{scss → theme}/config/mixins/_spacing.scss +0 -0
- /package/{scss → theme}/config/mixins/_stat-card.scss +0 -0
- /package/{scss → theme}/config/mixins/_stepper.scss +0 -0
- /package/{scss → theme}/config/mixins/_timeline.scss +0 -0
- /package/{scss → theme}/config/mixins/_transitions.scss +0 -0
- /package/{scss → theme}/config/mixins/_translations.scss +0 -0
- /package/{scss → theme}/tabler-icons.txt +0 -0
|
@@ -1,32 +1,45 @@
|
|
|
1
1
|
# ln-core
|
|
2
2
|
|
|
3
3
|
Shared helper module imported by all components — re-exported from
|
|
4
|
-
`
|
|
5
|
-
MutationObserver. Source: `
|
|
4
|
+
`components/ln-core/index.js`. No DOM attribute, no constructor, no
|
|
5
|
+
MutationObserver. Source: `components/ln-core/`.
|
|
6
6
|
|
|
7
7
|
## Helpers
|
|
8
8
|
|
|
9
9
|
ln-core exposes helpers in these categories:
|
|
10
10
|
|
|
11
11
|
- **Templates** — clone and populate `<template>` fragments
|
|
12
|
-
- **Events** — dispatch standard
|
|
12
|
+
- **Events & Lifecycle** — dispatch standard/cancelable CustomEvents; shared data-request cycle (`requestData`); `registerComponent` for MutationObserver-backed auto-init
|
|
13
13
|
- **DOM binding** — declarative data-attribute-driven rendering (`fill`, `renderList`, `fillTemplate`)
|
|
14
|
-
- **Forms** — serialize/populate by field `name`
|
|
15
|
-
- **
|
|
16
|
-
- **Discovery** — `registerComponent` for MutationObserver-backed auto-init
|
|
14
|
+
- **Forms & Inputs** — serialize/populate by field `name`, intercept input value getters/setters (`interceptValueProperty`)
|
|
15
|
+
- **Target & Event Predicates** — `shouldIgnoreClick`, `isTargetDisabled`, `isUsableTarget`, `isEditableTarget`
|
|
17
16
|
- **Reactivity** — `reactiveState`, `deepReactive`, `createBatcher`
|
|
18
17
|
- **Windowing** — sliding-window sparse cache for server-side virtualization (`createWindowCache`)
|
|
19
|
-
- **Layout** — viewport-aware positioning
|
|
20
|
-
- **
|
|
21
|
-
- **Hash codec** — namespaced URL fragment state (`hashParse`, `hashGet`, `hashSet`)
|
|
18
|
+
- **Layout & Positioning** — viewport-aware positioning (`computePlacement`), measurement (`measureHidden`)
|
|
19
|
+
- **Hash codec** — namespaced URL fragment state (`hashParse`, `hashGet`, `hashSet`, `hashSortEncode`, `hashSortDecode`, `hashFilterEncode`, `hashFilterDecode`, `resolveHashNamespace`)
|
|
22
20
|
- **Cryptography** — high-performance Web Crypto helpers for encryption at rest (`crypto.js`)
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
- **Searching & Filtering** — query tokenization, multi-field and filter matching (`matching.js`)
|
|
22
|
+
- **Comparing & Sorting** — type inference and localized/numeric comparison (`compare.js`)
|
|
23
|
+
- **Progress Math** — clamp and percentage calculations (`progress.js`)
|
|
24
|
+
- **Date Utilities** — flexible date input parsing and ISO formatting (`date.js`)
|
|
25
|
+
- **Number Utilities** — locale-aware separators, number sanitizing, parsing, and formatting (`number.js`)
|
|
26
|
+
- **Attribute Contracts & Parsers** — attribute specs, live getters, typed readers, and dev-time validation (`attrSpec`, `defineAttrs`, `attrStr`, `attrInt`, `attrFloat`, `attrBool`, `attrEnum`, `attrJson`, `validateAttrValue`, `isDevMode`) (`attrs.js`)
|
|
27
|
+
|
|
28
|
+
Source of truth: modular sub-files in `components/ln-core/`. Import from `'../../ln-core'` (barrel).
|
|
29
|
+
|
|
30
|
+
## Core Helpers & Submodules (`helpers.js`)
|
|
31
|
+
|
|
32
|
+
`helpers.js` serves as the centralized, backward-compatible named barrel re-exporting the specialized domain submodules:
|
|
33
|
+
- `template.js` — template cloning, declarative DOM binding (`fill`, `lnFill`, `fillTemplate`, `renderList`, `buildDict`).
|
|
34
|
+
- `events.js` — CustomEvent dispatchers (`dispatch`, `dispatchCancelable`, `requestData`), debug sinks and dev mode checks.
|
|
35
|
+
- `dom.js` — DOM guard and interactive target predicates (`guardBody`, `isVisible`, `shouldIgnoreClick`, `isUsableTarget`, etc.).
|
|
36
|
+
- `form.js` — form method resolution, serialization, population, and `interceptValueProperty`.
|
|
37
|
+
- `http.js` — URL assembly, HTTP headers compilation/parsing, and data mapper registry.
|
|
38
|
+
- `locale.js` — locale detection (`getLocale`), observer, and locale fallback registry.
|
|
39
|
+
- `lifecycle.js` — component registration (`registerComponent`), element scanning (`findElements`), and shared MutationObservers.
|
|
25
40
|
|
|
26
41
|
---
|
|
27
42
|
|
|
28
|
-
## helpers.js
|
|
29
|
-
|
|
30
43
|
### cloneTemplate(name, componentTag)
|
|
31
44
|
|
|
32
45
|
Clone a `<template data-ln-template="name">` element. Cached after first lookup.
|
|
@@ -114,12 +127,12 @@ window.lnCore.lnFill(modalEl, record); // record → fill; null → reset/clea
|
|
|
114
127
|
|
|
115
128
|
- Also dispatches `ln-fill` at `container` itself when it matches
|
|
116
129
|
`[data-ln-form]` or `[data-ln-fillable]` — so `lnFill(formEl, record)` works
|
|
117
|
-
when called directly on a form element. Source: `
|
|
130
|
+
when called directly on a form element. Source: `components/ln-core/template.js` (`lnFill`).
|
|
118
131
|
- `container` — any element; scans its entire subtree.
|
|
119
132
|
- `record` — plain object or `null`.
|
|
120
133
|
- Dispatches `ln-fill` (`bubbles: true`, `detail = record ?? null`) at each target.
|
|
121
134
|
- Returns `container` for chaining.
|
|
122
|
-
- Exported from `
|
|
135
|
+
- Exported from `components/ln-core/index.js`; available at `window.lnCore.lnFill`.
|
|
123
136
|
- Back-compat: `ln-form` also still accepts `ln-form:fill` / `ln-form:reset` (aliases).
|
|
124
137
|
|
|
125
138
|
### fillTemplate(clone, data)
|
|
@@ -143,7 +156,7 @@ fillTemplate(frag, { text: 'Engineering' });
|
|
|
143
156
|
root element itself when it is an `Element`, since `querySelectorAll` does not include
|
|
144
157
|
root). For each attribute whose value contains `{{`, replaces tokens via
|
|
145
158
|
`el.setAttribute(attr.name, resolved)`. Uses `setAttribute` — never `innerHTML` —
|
|
146
|
-
so injection risk is the same as `data-ln-attr`. Source: `
|
|
159
|
+
so injection risk is the same as `data-ln-attr`. Source: `components/ln-core/template.js` (`fillTemplate`).
|
|
147
160
|
- Missing keys produce empty string in both passes
|
|
148
161
|
- No-op in either pass when no `{{` is present
|
|
149
162
|
- Returns `clone` for chaining
|
|
@@ -153,7 +166,7 @@ fillTemplate(frag, { text: 'Engineering' });
|
|
|
153
166
|
|
|
154
167
|
### renderList(container, items, templateName, keyFn, fillFn, componentTag)
|
|
155
168
|
|
|
156
|
-
Keyed list rendering with DOM reuse. Existing children matched by `data-ln-key` attribute.
|
|
169
|
+
Keyed list rendering with DOM reuse. Existing children matched by `data-ln-render-key` attribute.
|
|
157
170
|
|
|
158
171
|
```js
|
|
159
172
|
renderList(
|
|
@@ -168,7 +181,7 @@ renderList(
|
|
|
168
181
|
|
|
169
182
|
- `keyFn(item)` returns a unique string key for each item
|
|
170
183
|
- `fillFn(el, item, index)` updates the DOM element with item data
|
|
171
|
-
- Reuses existing elements with matching `data-ln-key` (avoids re-clone)
|
|
184
|
+
- Reuses existing elements with matching `data-ln-render-key` (avoids re-clone)
|
|
172
185
|
- Replaces all container children atomically (`textContent = '' + appendChild(frag)`)
|
|
173
186
|
- Calls `fillTemplate(clone, item)` automatically for newly-cloned elements — `{{ key }}` placeholders in the template resolve from the item data without extra wiring.
|
|
174
187
|
|
|
@@ -295,12 +308,12 @@ populated.forEach(function (el) { dispatch(el, 'input'); });
|
|
|
295
308
|
- **Decoupled fill key (`data-ln-fill-as`)** — match key for the fill direction is
|
|
296
309
|
`el.getAttribute('data-ln-fill-as') || el.name`. When `data-ln-fill-as` is set,
|
|
297
310
|
the record key is the fill-as value and `name` stays as the form submission key.
|
|
298
|
-
Source: `populateForm` in `
|
|
311
|
+
Source: `populateForm` in `components/ln-core/form.js`.
|
|
299
312
|
- **Checkbox string coercion** — a single checkbox (one element with that `name` in
|
|
300
313
|
the form) whose fill value is a string is coerced via `_coerceBool`: `"false"`,
|
|
301
314
|
`"0"`, `""`, `"off"`, `"no"` (case-insensitive, trimmed) → unchecked; anything
|
|
302
315
|
else → checked. This handles `data-ln-fill-*` values which always arrive as
|
|
303
|
-
strings. Source: `_coerceBool` + `populateForm` in `
|
|
316
|
+
strings. Source: `_coerceBool` + `populateForm` in `components/ln-core/form.js`.
|
|
304
317
|
- Checkbox + array → `checked` if `el.value` is in the array.
|
|
305
318
|
- Checkbox group (same `name`, 2+ elements) + scalar → treated as comma-separated list (`"admin,editor"` → membership check).
|
|
306
319
|
- Single checkbox + scalar → boolean coercion: `"false"/"0"/"off"/"no"/""` → unchecked; anything else → checked.
|
|
@@ -326,11 +339,13 @@ Read the raw machine value behind a formatted cell/item display. The single
|
|
|
326
339
|
read path for value-based sort/filter across components.
|
|
327
340
|
|
|
328
341
|
```js
|
|
329
|
-
const raw = readValue(td); // '1250.50' from data-ln-value, else trimmed text
|
|
342
|
+
const raw = readValue(td); // '1250.50' from data-ln-value, datetime on <time>, value on <data>, else trimmed text
|
|
330
343
|
```
|
|
331
344
|
|
|
332
345
|
- Returns `data-ln-value` attribute value if the element has it.
|
|
333
|
-
-
|
|
346
|
+
- Returns `datetime` attribute if the element is `<time>` and has it.
|
|
347
|
+
- Returns `value` attribute if the element is `<data>` and has it.
|
|
348
|
+
- Otherwise falls back to `el.textContent.trim()`.
|
|
334
349
|
- Used by `ln-table` for sort/filter.
|
|
335
350
|
|
|
336
351
|
### registerComponent(selector, attribute, ComponentFn, componentTag, options)
|
|
@@ -345,8 +360,9 @@ import { registerComponent } from '../ln-core';
|
|
|
345
360
|
function _component(dom) { this.dom = dom; /* ... */ }
|
|
346
361
|
|
|
347
362
|
registerComponent('data-ln-example', 'lnExample', _component, 'ln-example', {
|
|
348
|
-
|
|
349
|
-
|
|
363
|
+
effects: {
|
|
364
|
+
'data-ln-example-state': function (target, name, oldValue) { /* attribute → state bridge */ }
|
|
365
|
+
},
|
|
350
366
|
onInit: function (root) { /* post-init hook, per added subtree */ }
|
|
351
367
|
});
|
|
352
368
|
```
|
|
@@ -355,18 +371,172 @@ registerComponent('data-ln-example', 'lnExample', _component, 'ln-example', {
|
|
|
355
371
|
if it contains `[`, `.`, or `#` (e.g. `'[data-ln-foo]:not([disabled])'`).
|
|
356
372
|
- `attribute` — JS-side key used both as `window[attribute]` (the
|
|
357
373
|
constructor function) and `el[attribute]` (the per-element instance).
|
|
358
|
-
- `options.
|
|
359
|
-
the
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
-
|
|
364
|
-
|
|
374
|
+
- `options.attributes` — the component's attribute table. One entry per host
|
|
375
|
+
attribute the component reads or reacts to. Derives the `effects` map, the
|
|
376
|
+
live-getter spec (via `attrSpec` at call site), and scopes `options.onAttrChange` —
|
|
377
|
+
only declared keys reach the catch-all. When present, `options.effects` is ignored.
|
|
378
|
+
- `options.effects` — `{ attributeName: handler(target, name, oldValue) }`.
|
|
379
|
+
A per-attribute reaction dispatched by the shared attribute observer's
|
|
380
|
+
registry. Fires when the mutated element already owns an instance
|
|
381
|
+
(`el[attribute]` is truthy) and the attribute name starts with `data-ln-`.
|
|
382
|
+
- `options.onAttrChange(target, name, oldValue)` — catch-all reaction for
|
|
383
|
+
any `data-ln-*` attribute on the host not covered by an `effects` key and
|
|
384
|
+
present in `options.attributes` when a table is supplied. Without a table, the
|
|
385
|
+
catch-all is unscoped and fires for every `data-ln-*` attribute on the host.
|
|
386
|
+
Same instance and prefix gate as `effects`.
|
|
387
|
+
- `options.onAttributeChange(target, attrName)` — called when an attribute
|
|
388
|
+
in this registration's observed set (the selector's own attribute name,
|
|
389
|
+
plus `extraAttributes`) changes on an already-initialized element. The
|
|
365
390
|
attribute → state bridge hook.
|
|
391
|
+
- `options.extraAttributes` — additional attribute names, beyond the
|
|
392
|
+
selector's own, added to this registration's observed set in the shared
|
|
393
|
+
attribute registry (e.g. state attributes set by a coordinator). Read by
|
|
394
|
+
the `onAttributeChange` path.
|
|
366
395
|
- `options.onInit(root)` — called after `findElements` per subtree
|
|
367
396
|
(initial DOM, added childList nodes, attribute-mutated subtrees).
|
|
397
|
+
- `options.onSubtreeChange(host, mutation)` — called on every `childList`
|
|
398
|
+
mutation inside this registration's observed subtree, where `host` is the
|
|
399
|
+
nearest ancestor (or the mutated node itself) matching `selector`. Runs
|
|
400
|
+
alongside, not instead of, the added/removed-node instantiation and
|
|
401
|
+
teardown `registerComponent` already performs.
|
|
368
402
|
- Returns the constructor function (also stored at `window[attribute]`).
|
|
369
403
|
|
|
404
|
+
### observeAttributes(names, handler)
|
|
405
|
+
|
|
406
|
+
For components that own their own lifecycle (bespoke `childList` logic that
|
|
407
|
+
doesn't fit `registerComponent`'s shape) and need only the attribute half of
|
|
408
|
+
the shared attribute-observer invariant.
|
|
409
|
+
|
|
410
|
+
```js
|
|
411
|
+
import { observeAttributes } from '../ln-core';
|
|
412
|
+
|
|
413
|
+
observeAttributes(['href'], function (el, name, oldValue) {
|
|
414
|
+
_processLink(el);
|
|
415
|
+
});
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
- `names` — attribute names to watch. No `data-ln-` prefix gate, no instance
|
|
419
|
+
gate — every mutation of a watched name calls `handler`, on any element.
|
|
420
|
+
- `handler(el, attributeName, oldValue)`.
|
|
421
|
+
- Installs onto the same shared `MutationObserver` used by `registerComponent`
|
|
422
|
+
(one observer on `document.body`, no `attributeFilter`).
|
|
423
|
+
- A component using `observeAttributes` must **not** run its own attribute
|
|
424
|
+
`MutationObserver` alongside it — that duplicates delivery.
|
|
425
|
+
- Two standing exceptions keep their own private observer instead of using
|
|
426
|
+
this: `ln-progress` (observes an attribute on its **parent**, outside the
|
|
427
|
+
host-only boundary the shared observer covers) and `ln-icon` (the only
|
|
428
|
+
component in the library that imports nothing — pulling in `ln-core`'s
|
|
429
|
+
module-level side effects would roughly quadruple its standalone bundle
|
|
430
|
+
size). Neither is an oversight; do not migrate them.
|
|
431
|
+
|
|
432
|
+
### setPersistSink(sink)
|
|
433
|
+
|
|
434
|
+
Nullable persist restore/save sink. Installed/removed only by `ln-persist`
|
|
435
|
+
(`components/ln-persist/src/ln-persist.js`) — mirrors `setDebugSink`'s shape
|
|
436
|
+
exactly. `findElements` calls `window.lnCore._persistSink(el, selector)`
|
|
437
|
+
for any element carrying `data-ln-persist`, immediately before constructing
|
|
438
|
+
its owning component's instance, when the sink is installed.
|
|
439
|
+
|
|
440
|
+
```js
|
|
441
|
+
import { setPersistSink } from '../ln-core';
|
|
442
|
+
|
|
443
|
+
setPersistSink(function (el, selector) {
|
|
444
|
+
// restore/save logic keyed off the registry's persist: entries
|
|
445
|
+
});
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
- `sink(el, selector)` — called synchronously inside `findElements`, before
|
|
449
|
+
the element's component instance is constructed.
|
|
450
|
+
- No sink installed (`ln-persist` not loaded) → the check is a no-op.
|
|
451
|
+
- See `components/ln-persist/README.md` for the full restore/save contract.
|
|
452
|
+
|
|
453
|
+
### defineAttrs(instance, dom, spec), attrSpec(table), attrEffects(table)
|
|
454
|
+
|
|
455
|
+
Define live, getter-only properties on a component instance that read the DOM
|
|
456
|
+
on every access. One table per component is the single source of truth for its
|
|
457
|
+
host attributes, feeding `defineAttrs` via `attrSpec` and `registerComponent` via
|
|
458
|
+
`attributes`.
|
|
459
|
+
|
|
460
|
+
```js
|
|
461
|
+
import { registerComponent, defineAttrs, attrSpec, attrInt, attrBool, attrList } from '../ln-core';
|
|
462
|
+
|
|
463
|
+
const ATTRIBUTES = {
|
|
464
|
+
'data-ln-example-window': { prop: '_windowSize', read: attrInt, fallback: 1000, effect: _applyWindowSize },
|
|
465
|
+
'data-ln-example-tags': { prop: '_tags', read: attrList },
|
|
466
|
+
'data-ln-example-no-sync': { prop: 'noSync', read: attrBool }
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
const ATTR_SPEC = attrSpec(ATTRIBUTES);
|
|
470
|
+
|
|
471
|
+
function _component(dom) {
|
|
472
|
+
defineAttrs(this, dom, ATTR_SPEC);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
registerComponent('data-ln-example', 'lnExample', _component, 'ln-example', {
|
|
476
|
+
attributes: ATTRIBUTES
|
|
477
|
+
});
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
- `table` — `{ [attributeName]: { prop, read, fallback, effect } }`.
|
|
481
|
+
- `attrSpec(table)` — derives `{ propName: [reader, attributeName, fallback] }` for entries declaring `prop`.
|
|
482
|
+
- `attrEffects(table)` — derives `{ [attributeName]: effect }` for entries declaring `effect` (returns `null` when empty).
|
|
483
|
+
- `spec` — `{ propName: [reader, attributeName, fallback] }`.
|
|
484
|
+
- `attrStr` — returns `fallback` when the attribute is absent, else the raw
|
|
485
|
+
string.
|
|
486
|
+
- `attrInt` — `parseInt(..., 10)`; returns `fallback` on `NaN`. `"0"` stays
|
|
487
|
+
`0` — unlike the common `parseInt(attr, 10) || fallback` idiom, which maps
|
|
488
|
+
`"0"` to `fallback`. Check call sites relying on that idiom before swapping
|
|
489
|
+
them to `attrInt`.
|
|
490
|
+
- `attrBool` — `(el, name, fallback)`: returns `fallback` when the attribute is absent, `false` when `"false"` or `"0"`, and `true` otherwise (`""`, `"true"`, `"1"`).
|
|
491
|
+
- `attrList` — `(el.getAttribute(name) || '').split(',').map(trim).filter(Boolean)`.
|
|
492
|
+
Allocates a new array per read — do not call inside a per-row loop.
|
|
493
|
+
- `reader` can be any function of that `(el, name, fallback)` shape, so a
|
|
494
|
+
component can pass its own for special-cased parsing.
|
|
495
|
+
- **Getter-only — assignment throws** (`TypeError`, strict mode). Nothing is
|
|
496
|
+
copied into instance state, so there is no state to invalidate and no sync
|
|
497
|
+
step; a drifting copy is structurally impossible. Before migrating an
|
|
498
|
+
existing `this.prop = ...` assignment to a `defineAttrs` getter, grep for
|
|
499
|
+
every place the codebase assigns to that property after construction — a
|
|
500
|
+
hit means the property is not a pure attribute mirror and does not belong
|
|
501
|
+
in the spec. (`ln-data-store`'s `windowed` is excluded for exactly this
|
|
502
|
+
reason: `destroy()` assigns `this.windowed = false`.)
|
|
503
|
+
- **Attribute names must be inline string literals or a `const` bound to a
|
|
504
|
+
literal — never concatenated or templated.**
|
|
505
|
+
`scripts/sync-ln-schemas.mjs:22-23` is a raw regex over file text; a
|
|
506
|
+
constructed name is invisible to it and the CI docs gate breaks silently.
|
|
507
|
+
|
|
508
|
+
### Frozen-attribute convention
|
|
509
|
+
|
|
510
|
+
A **frozen attribute** is a constructor-only attribute — one that physically
|
|
511
|
+
cannot be re-read at runtime (e.g. an IndexedDB schema fixed at open time).
|
|
512
|
+
When a frozen attribute is edited after init, the component writes
|
|
513
|
+
`data-ln-{component}-frozen` on its own host, with the attempted attribute
|
|
514
|
+
name as the value, and a co-located `*-dev.scss` rule surfaces it through the
|
|
515
|
+
`dev-dom-error` mixin under `[data-ln-debug]`. Never `console.warn` for this
|
|
516
|
+
case — it is a CSS-only dev affordance. See `ln-data-store` for the reference
|
|
517
|
+
implementation (`_markFrozen`, `ln-data-store-dev.scss`).
|
|
518
|
+
|
|
519
|
+
### holdInit() / releaseInit() / pendingCount() / queueBoot(fn)
|
|
520
|
+
|
|
521
|
+
Boot gating primitives for asynchronous loading (such as external partial templates). Prevents components from initializing (sweeping the DOM) before all external resources have finished loading.
|
|
522
|
+
|
|
523
|
+
```js
|
|
524
|
+
import { holdInit, releaseInit, pendingCount, queueBoot } from '../ln-core';
|
|
525
|
+
|
|
526
|
+
// In an async component's initialization:
|
|
527
|
+
holdInit();
|
|
528
|
+
fetch('/tpl.html').then(html => {
|
|
529
|
+
// populate DOM
|
|
530
|
+
releaseInit();
|
|
531
|
+
});
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
- `holdInit()` — Increments the global boot holds counter (`window.lnCore._bootHolds`).
|
|
535
|
+
- `releaseInit()` — Decrements the global boot holds counter. If the counter reaches zero, it drains the queue (`window.lnCore._bootQueue`) in push order.
|
|
536
|
+
- `pendingCount()` — Returns the current number of active boot holds.
|
|
537
|
+
- `queueBoot(fn)` — If `pendingCount() > 0`, queues the function in `_bootQueue`. Otherwise, schedules it immediately using `setTimeout(fn, 0)` (to match standard event loop scheduling).
|
|
538
|
+
- Used internally by `registerComponent` and `ln-ui-coordinator` to prevent race conditions during async initialization.
|
|
539
|
+
|
|
370
540
|
---
|
|
371
541
|
|
|
372
542
|
## reactive.js
|
|
@@ -448,7 +618,7 @@ the DOM will thrash.
|
|
|
448
618
|
|
|
449
619
|
For the full decision matrix (`reactiveState` vs `deepReactive`, when
|
|
450
620
|
to use this pattern at all, anti-patterns), see
|
|
451
|
-
[Reactive Rendering Pattern in
|
|
621
|
+
[Reactive Rendering Pattern in components/COMPONENTS.md](../../components/COMPONENTS.md#reactive-rendering-pattern).
|
|
452
622
|
|
|
453
623
|
---
|
|
454
624
|
|
|
@@ -549,26 +719,6 @@ panel.setAttribute('data-ln-placement', placement);
|
|
|
549
719
|
pair → clamps to viewport edge if nothing fits.
|
|
550
720
|
- Pure function. No DOM side effects.
|
|
551
721
|
|
|
552
|
-
### teleportToBody(el)
|
|
553
|
-
|
|
554
|
-
Move an element into `<body>`, leaving a comment placeholder so it can
|
|
555
|
-
be restored to its original parent.
|
|
556
|
-
|
|
557
|
-
```js
|
|
558
|
-
const restore = teleportToBody(panel);
|
|
559
|
-
// ... later
|
|
560
|
-
restore();
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
- Returns a cleanup function that restores the element to its origin.
|
|
564
|
-
- No-op + no-op cleanup if the element is already in `<body>` or
|
|
565
|
-
parent is missing.
|
|
566
|
-
- Used for floating UI that needs to escape `overflow: hidden`
|
|
567
|
-
ancestors (popovers, dropdowns).
|
|
568
|
-
- Does NOT set inline styles — the caller's CSS rule (e.g.
|
|
569
|
-
`[data-ln-popover] { position: fixed }`) is responsible for
|
|
570
|
-
positioning context.
|
|
571
|
-
|
|
572
722
|
### measureHidden(el)
|
|
573
723
|
|
|
574
724
|
Read `offsetWidth` / `offsetHeight` of an element that may currently
|
|
@@ -587,93 +737,8 @@ const { width, height } = measureHidden(panel);
|
|
|
587
737
|
|
|
588
738
|
---
|
|
589
739
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
### persistGet(component, el)
|
|
593
|
-
|
|
594
|
-
Read persisted value for an element. Returns the parsed JSON value or `null` (not found, or storage unavailable).
|
|
595
|
-
|
|
596
|
-
- `component` — component name string (e.g. `'toggle'`, `'tabs'`, `'filter'`)
|
|
597
|
-
- `el` — DOM element with `data-ln-persist` attribute
|
|
598
|
-
|
|
599
|
-
Storage key resolved from `el`: uses `data-ln-persist` value if non-empty, otherwise element's `id`. If neither exists, emits `console.warn` and returns `null`.
|
|
600
|
-
|
|
601
|
-
```js
|
|
602
|
-
import { persistGet } from '../ln-core';
|
|
603
|
-
const saved = persistGet('toggle', el); // null | 'open' | 'close'
|
|
604
|
-
```
|
|
605
|
-
|
|
606
|
-
### persistSet(component, el, value)
|
|
607
|
-
|
|
608
|
-
Write a value to localStorage. Value is JSON-serialized. Silently no-ops if localStorage is unavailable or full.
|
|
609
|
-
|
|
610
|
-
```js
|
|
611
|
-
import { persistSet } from '../ln-core';
|
|
612
|
-
persistSet('toggle', el, 'open');
|
|
613
|
-
persistSet('sort', el, { field: 'name', column: null, direction: 'desc' });
|
|
614
|
-
persistSet('filter', el, null); // explicitly clears
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
### persistRemove(component, el)
|
|
618
|
-
|
|
619
|
-
Remove a single persisted value for a specific element.
|
|
620
|
-
|
|
621
|
-
```js
|
|
622
|
-
import { persistRemove } from '../ln-core';
|
|
623
|
-
persistRemove('tabs', el);
|
|
624
|
-
```
|
|
625
|
-
|
|
626
|
-
### persistClear(component)
|
|
627
|
-
|
|
628
|
-
Remove ALL persisted values for a given component type. Scans all localStorage keys matching `ln:{component}:*`.
|
|
629
|
-
|
|
630
|
-
```js
|
|
631
|
-
import { persistClear } from '../ln-core';
|
|
632
|
-
persistClear('toggle'); // removes all ln:toggle:* keys
|
|
633
|
-
persistClear('sort'); // removes all ln:sort:* keys
|
|
634
|
-
```
|
|
635
|
-
|
|
636
|
-
Useful for "reset to defaults" functionality.
|
|
637
|
-
|
|
638
|
-
### Storage key format
|
|
639
|
-
|
|
640
|
-
```
|
|
641
|
-
ln:{component}:{pagePath}:{id}
|
|
642
|
-
```
|
|
643
|
-
|
|
644
|
-
- `pagePath` — `location.pathname`, lowercase, trailing slash stripped, or `/` for root
|
|
645
|
-
- `id` — element's `id` attribute, or the explicit `data-ln-persist="custom-key"` value
|
|
646
|
-
|
|
647
|
-
Examples:
|
|
648
|
-
```
|
|
649
|
-
ln:toggle:/admin/users:sidebar
|
|
650
|
-
ln:tabs:/settings:settings-tabs
|
|
651
|
-
ln:sort:/admin/orders:orders-table-name
|
|
652
|
-
ln:filter:/admin/users:status-filter
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
### Opt-in HTML attribute
|
|
656
|
-
|
|
657
|
-
```html
|
|
658
|
-
<!-- Uses element id as storage key -->
|
|
659
|
-
<section id="sidebar" data-ln-toggle="close" data-ln-persist>
|
|
660
|
-
|
|
661
|
-
<!-- Explicit key (no id needed) -->
|
|
662
|
-
<section data-ln-toggle="close" data-ln-persist="sidebar-section">
|
|
663
|
-
```
|
|
664
|
-
|
|
665
|
-
Persistence is always opt-in. Elements without `data-ln-persist` are never touched.
|
|
666
|
-
|
|
667
|
-
Components that support `data-ln-persist` document the stored value
|
|
668
|
-
shape in their own READMEs (ln-toggle, ln-accordion, ln-tabs,
|
|
669
|
-
ln-sort, ln-filter).
|
|
670
|
-
|
|
671
|
-
### Graceful degradation
|
|
672
|
-
|
|
673
|
-
- localStorage disabled (private browsing) → silent no-op, components work normally without persistence
|
|
674
|
-
- localStorage full → silent no-op on write, existing data preserved
|
|
675
|
-
- Stale data (panel removed from DOM, column index out of range) → orphan key ignored gracefully
|
|
676
|
-
- Missing `id` + no explicit key → `console.warn` once, persistence skipped for that element
|
|
740
|
+
Persistence now lives in the standalone `ln-persist` component — see
|
|
741
|
+
`components/ln-persist/README.md`.
|
|
677
742
|
|
|
678
743
|
---
|
|
679
744
|
|
|
@@ -763,15 +828,17 @@ const key = getCryptoKey(); // null or CryptoKey
|
|
|
763
828
|
|
|
764
829
|
- **Returns** `CryptoKey` or `null` if no key has been derived yet.
|
|
765
830
|
|
|
766
|
-
### encryptData(plainData,
|
|
831
|
+
### encryptData(plainData, keyOrOptions = null)
|
|
767
832
|
|
|
768
|
-
Encrypt any serializable value (objects/arrays are converted to JSON strings).
|
|
833
|
+
Encrypt any serializable value (objects/arrays are converted to JSON strings). Enforces fail-closed semantics (throws `Error` if no key is set or encryption fails).
|
|
769
834
|
|
|
770
835
|
```js
|
|
771
836
|
import { encryptData } from '../ln-core';
|
|
772
837
|
|
|
773
838
|
const result = await encryptData({ text: 'Sensitive message' });
|
|
774
839
|
// {
|
|
840
|
+
// v: 1,
|
|
841
|
+
// alg: 'AES-GCM',
|
|
775
842
|
// encrypted: true,
|
|
776
843
|
// iv: 'base64-iv-string...',
|
|
777
844
|
// data: 'base64-ciphertext...'
|
|
@@ -779,23 +846,134 @@ const result = await encryptData({ text: 'Sensitive message' });
|
|
|
779
846
|
```
|
|
780
847
|
|
|
781
848
|
- **`plainData`** — any primitive value, array, or object.
|
|
782
|
-
- **`
|
|
783
|
-
- **Returns** `Promise<Object>` containing `encrypted: true`,
|
|
849
|
+
- **`keyOrOptions`** — optional custom `CryptoKey` or options object `{ key?: CryptoKey }`. Defaults to the active key.
|
|
850
|
+
- **Returns** `Promise<Object>` containing version 1 envelope (`v: 1`, `alg: 'AES-GCM'`, `encrypted: true`, `iv`, `data`). Throws `Error` on failure.
|
|
784
851
|
|
|
785
|
-
### decryptData(encryptedObject,
|
|
852
|
+
### decryptData(encryptedObject, keyOrOptions = null)
|
|
786
853
|
|
|
787
|
-
Decrypt an encrypted
|
|
854
|
+
Decrypt an encrypted envelope back into its original form (automatically parsing JSON strings back to objects). Supports both v1 envelopes and legacy v0 unversioned envelopes. Enforces fail-closed semantics unless `{ silent: true }` is specified.
|
|
788
855
|
|
|
789
856
|
```js
|
|
790
857
|
import { decryptData } from '../ln-core';
|
|
791
858
|
|
|
792
859
|
const decrypted = await decryptData(result);
|
|
793
860
|
console.log(decrypted.text); // 'Sensitive message'
|
|
861
|
+
|
|
862
|
+
// Resilient bulk-read mode:
|
|
863
|
+
const resilient = await decryptData(corruptObject, { silent: true });
|
|
864
|
+
// returns { ...corruptObject, decryptionError: true } instead of throwing
|
|
794
865
|
```
|
|
795
866
|
|
|
796
867
|
- **`encryptedObject`** — an object generated by `encryptData`.
|
|
797
|
-
- **`
|
|
798
|
-
- **Returns** `Promise<any>`. The original plain data
|
|
868
|
+
- **`keyOrOptions`** — optional custom `CryptoKey` or options object `{ key?: CryptoKey, silent?: boolean }`.
|
|
869
|
+
- **Returns** `Promise<any>`. The original plain data. Throws `Error` on decryption failure or missing key unless `{ silent: true }` is passed.
|
|
870
|
+
|
|
871
|
+
---
|
|
872
|
+
|
|
873
|
+
## matching.js
|
|
874
|
+
|
|
875
|
+
Pure string searching, tokenization, and multi-filter matching engine.
|
|
876
|
+
|
|
877
|
+
### normalizeSearchTerm(raw)
|
|
878
|
+
|
|
879
|
+
Trims and lowercases user search queries.
|
|
880
|
+
|
|
881
|
+
### tokenizeSearchQuery(raw)
|
|
882
|
+
|
|
883
|
+
Splits query on whitespace for multi-term AND matching. Returns an array of lowercase search tokens.
|
|
884
|
+
|
|
885
|
+
### matchesSearchTokens(text, tokens)
|
|
886
|
+
|
|
887
|
+
Evaluates whether text contains all search tokens (case-insensitive AND match).
|
|
888
|
+
|
|
889
|
+
### matchesFilterValues(text, values)
|
|
890
|
+
|
|
891
|
+
Evaluates whether text matches any of the active filter values (case-insensitive OR match).
|
|
892
|
+
|
|
893
|
+
---
|
|
894
|
+
|
|
895
|
+
## compare.js
|
|
896
|
+
|
|
897
|
+
Type inference and localized/numeric comparison engine.
|
|
898
|
+
|
|
899
|
+
### detectValueType(values)
|
|
900
|
+
|
|
901
|
+
Iterates values in a dataset or column. If all non-empty values are finite numbers, returns `'number'`; otherwise returns `'string'`.
|
|
902
|
+
|
|
903
|
+
### compareValues(a, b, type, locale)
|
|
904
|
+
|
|
905
|
+
Performs null-safe comparison (-1, 0, 1):
|
|
906
|
+
- `null`/`undefined` collation: sorts first or last deterministically.
|
|
907
|
+
- `type === 'number'`: numeric difference `a - b`.
|
|
908
|
+
- `type === 'string'`: localized comparison via `Intl.Collator(locale, { numeric: true, sensitivity: 'base' })`.
|
|
909
|
+
|
|
910
|
+
---
|
|
911
|
+
|
|
912
|
+
## progress.js
|
|
913
|
+
|
|
914
|
+
Pure mathematical clamping and progress calculations.
|
|
915
|
+
|
|
916
|
+
### calculateProgress(rawValue, rawMax, min = 0)
|
|
917
|
+
|
|
918
|
+
Computes `{ value, min, max, clampedValue, percentage }` where percentage is bounded between 0% and 100%.
|
|
919
|
+
|
|
920
|
+
---
|
|
921
|
+
|
|
922
|
+
## date.js
|
|
923
|
+
|
|
924
|
+
Pure date input parsing and ISO formatting.
|
|
925
|
+
|
|
926
|
+
### parseDateInput(raw)
|
|
927
|
+
|
|
928
|
+
Parses Date objects, ISO strings (`YYYY-MM-DD` or `YYYY-MM-DDTHH:mm:ssZ`), and Unix seconds/milliseconds timestamps into a valid `Date` instance (or `null` if invalid).
|
|
929
|
+
|
|
930
|
+
A date-only `YYYY-MM-DD` string is read as local midnight of that calendar day, not UTC midnight (the native `Date` reading), so it round-trips through `formatDateToISO` unchanged in every timezone. A non-existent calendar date (`2026-02-31`) returns `null`.
|
|
931
|
+
|
|
932
|
+
### formatDateToISO(date)
|
|
933
|
+
|
|
934
|
+
Converts a `Date` instance to standard `YYYY-MM-DD` string representation.
|
|
935
|
+
|
|
936
|
+
---
|
|
937
|
+
|
|
938
|
+
## number.js
|
|
939
|
+
|
|
940
|
+
Locale-aware number sanitizing, parsing, and formatting with cached `Intl.NumberFormat` instances.
|
|
941
|
+
|
|
942
|
+
### getSeparators(locale)
|
|
943
|
+
|
|
944
|
+
Extracts group and decimal separators dynamically from `Intl.NumberFormat` for any BCP 47 locale tag (e.g. `'en-US'`, `'mk-MK'`, `'de-DE'`, `'fr-FR'`).
|
|
945
|
+
|
|
946
|
+
### cleanNumericString(raw, groupSep, decimalSep)
|
|
947
|
+
|
|
948
|
+
Strips currency symbols, whitespace, and thousands separators, normalizing the decimal separator to `.` for reliable `parseFloat`.
|
|
949
|
+
|
|
950
|
+
### parseNumber(raw, locale)
|
|
951
|
+
|
|
952
|
+
Parses localized user input or raw strings into a valid `Number` or `NaN`.
|
|
953
|
+
|
|
954
|
+
### formatNumber(num, locale, options)
|
|
955
|
+
|
|
956
|
+
Formats a numeric value using `Intl.NumberFormat` with cached formatters. Supports `maxDecimals` and `userDecimals` constraints.
|
|
957
|
+
|
|
958
|
+
---
|
|
959
|
+
|
|
960
|
+
## Target & Event Predicates (`dom.js`)
|
|
961
|
+
|
|
962
|
+
### shouldIgnoreClick(event)
|
|
963
|
+
|
|
964
|
+
Returns `true` if the mouse click was triggered with modifier keys (`Ctrl`, `Meta`, `Shift`, `Alt`) or a non-primary mouse button (`button !== 0`).
|
|
965
|
+
|
|
966
|
+
### isTargetDisabled(element)
|
|
967
|
+
|
|
968
|
+
Returns `true` if the element or any ancestor is disabled (`.disabled`), marked with `aria-disabled="true"`, or contained inside an `[inert]` element.
|
|
969
|
+
|
|
970
|
+
### isUsableTarget(element, action)
|
|
971
|
+
|
|
972
|
+
Returns `true` if the target is connected to the DOM, visible (`isVisible`), enabled (`!isTargetDisabled`), and implements the target method (e.g. `el.click` or `el.focus`).
|
|
973
|
+
|
|
974
|
+
### isEditableTarget(element)
|
|
975
|
+
|
|
976
|
+
Returns `true` if the element is an `<input>`, `<textarea>`, `<select>`, or `[contenteditable]` container where global shortcut keys should avoid triggering unless explicitly opted-in.
|
|
799
977
|
|
|
800
978
|
---
|
|
801
979
|
|
|
@@ -870,11 +1048,12 @@ Sort coerces with `parseFloat(raw) || 0`. Formatted display text breaks it:
|
|
|
870
1048
|
|
|
871
1049
|
### The split
|
|
872
1050
|
|
|
873
|
-
- `data-ln-value` — the VALUE. Universal. Read by `ln-core.readValue`.
|
|
1051
|
+
- `data-ln-value` — the VALUE. Universal raw attribute. Read by `ln-core.readValue`.
|
|
1052
|
+
- `datetime` / `value` — native HTML5 machine values on `<time>` and `<data>` elements, also read directly by `ln-core.readValue`.
|
|
874
1053
|
- **Type is inferred, not declared.** `ln-core.detectValueType` scans the current value set once
|
|
875
1054
|
per sort operation — no `data-ln-*-sort` type attribute exists anymore. All non-empty values
|
|
876
1055
|
finite numbers → numeric compare; otherwise `ln-core.compareValues` + `Intl.Collator` string
|
|
877
|
-
compare. See `
|
|
1056
|
+
compare. See `components/ln-sort/README.md`.
|
|
878
1057
|
|
|
879
1058
|
### The reader
|
|
880
1059
|
|
|
@@ -894,3 +1073,49 @@ the server's job: Blade/PHP in SSR mode, or the API payload in data-driven mode.
|
|
|
894
1073
|
- **Data-driven** — the raw value lives in the record field (API payload); the
|
|
895
1074
|
rendered element may also carry `data-ln-value`. Sorting runs on the record
|
|
896
1075
|
field. Never sort formatted text.
|
|
1076
|
+
|
|
1077
|
+
---
|
|
1078
|
+
|
|
1079
|
+
## attrs.js
|
|
1080
|
+
|
|
1081
|
+
Standardized attribute readers, spec generators, live getter mappers, and dev-time type validation.
|
|
1082
|
+
|
|
1083
|
+
### `attrStr(el, name, fallback)`
|
|
1084
|
+
Reads a string attribute. Returns `fallback` if attribute is null or empty.
|
|
1085
|
+
|
|
1086
|
+
### `attrInt(el, name, fallback)`
|
|
1087
|
+
Parses integer from attribute (`parseInt(val, 10)`). Returns `fallback` if parsing results in `NaN`.
|
|
1088
|
+
|
|
1089
|
+
### `attrFloat(el, name, fallback)`
|
|
1090
|
+
Parses floating point number from attribute (`parseFloat(val)`). Returns `fallback` if parsing results in `NaN`.
|
|
1091
|
+
|
|
1092
|
+
### `attrBool(el, name, fallback = false)`
|
|
1093
|
+
Evaluates boolean attribute presence and values. Returns `fallback` if attribute is absent. If present, returns `false` when value is `'false'` or `'0'`, and `true` otherwise (`""`, `'true'`, `'1'`).
|
|
1094
|
+
|
|
1095
|
+
### `attrEnum(values, fallback)`
|
|
1096
|
+
Higher-order function returning a cached reader function for a set of permitted string enum values. (Illustrative usage; authoritative contracts are defined in each component's documentation, e.g. [`ln-modal`](../../docs-mcp/components/ln-modal.md)):
|
|
1097
|
+
```js
|
|
1098
|
+
const readState = attrEnum(['open', 'close'], 'close');
|
|
1099
|
+
const state = readState(el, 'data-ln-modal');
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
### `attrJson(el, name, fallback)`
|
|
1103
|
+
Safely parses JSON string attribute. Returns `fallback` if attribute is missing or contains invalid JSON syntax.
|
|
1104
|
+
|
|
1105
|
+
### `attrSpec(spec)`
|
|
1106
|
+
Generates an attribute definition spec for `defineAttrs`. Automatically infers the appropriate reader function from `entry.type` if `entry.read` is omitted. For full component specifications, see individual component docs and schemas:
|
|
1107
|
+
```js
|
|
1108
|
+
// Illustrative attribute table combining host enum and typed options:
|
|
1109
|
+
const ATTRIBUTES = {
|
|
1110
|
+
'data-ln-modal': { type: 'enum', values: ['open', 'close'], fallback: 'close', effect: _syncAttribute },
|
|
1111
|
+
'data-ln-scroll-delay': { prop: 'delay', type: 'integer', fallback: 450 }
|
|
1112
|
+
};
|
|
1113
|
+
const ATTR_SPEC = attrSpec(ATTRIBUTES);
|
|
1114
|
+
```
|
|
1115
|
+
|
|
1116
|
+
### `defineAttrs(target, el, spec)`
|
|
1117
|
+
Installs live getters on `target` mapping property names to dynamic attribute reads on `el`.
|
|
1118
|
+
|
|
1119
|
+
### `validateAttrValue(entry, value, attrName, componentTag)`
|
|
1120
|
+
Validates attribute string against entry constraints (`enum`, `integer`, `float`, `boolean`, `min`, `max`, etc.) and outputs descriptive `console.warn` in dev mode.
|
|
1121
|
+
|