@livenetworks/ashlar 1.6.0 → 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/components/ln-confirm/README.md +216 -0
- 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 -167
- 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/README.md +0 -162
- 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
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { registerComponent, dispatch, dispatchCancelable } from '../../ln-core';
|
|
2
|
+
|
|
3
|
+
(function () {
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const DOM_SELECTOR = 'data-ln-picklist';
|
|
7
|
+
const DOM_ATTRIBUTE = 'lnPicklist';
|
|
8
|
+
const LIST_ATTR = 'data-ln-picklist-list';
|
|
9
|
+
const MAX_ATTR = 'data-ln-picklist-max';
|
|
10
|
+
|
|
11
|
+
if (window[DOM_ATTRIBUTE] !== undefined) return;
|
|
12
|
+
|
|
13
|
+
// ─── Attribute Contract (SSOT) ──────────────────────────
|
|
14
|
+
const ATTRIBUTES = {
|
|
15
|
+
'data-ln-picklist': { type: 'enum', values: ['enabled', 'disabled'], fallback: 'enabled', effect: _syncEnabled, description: 'Controls enabled/disabled state of the dual-list picklist' },
|
|
16
|
+
'data-ln-picklist-max': { type: 'integer', fallback: Infinity, min: 1, effect: _syncMax, description: 'Maximum selectable items in the selected list' },
|
|
17
|
+
'data-ln-picklist-list': { type: 'enum', values: ['available', 'selected'], description: 'Role marker for available or selected picklist columns' }
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// ─── Component ─────────────────────────────────────────────
|
|
21
|
+
//
|
|
22
|
+
// The checkbox IS the state. Its `checked` property and the list the item
|
|
23
|
+
// currently sits in are the same fact, and `name`/`value` carry the
|
|
24
|
+
// selection to the server natively — unchecked boxes are not submitted.
|
|
25
|
+
// Hence no hidden inputs, no state attribute and no JS mirror.
|
|
26
|
+
|
|
27
|
+
function _component(dom) {
|
|
28
|
+
this.dom = dom;
|
|
29
|
+
this.isEnabled = dom.getAttribute(DOM_SELECTOR) !== 'disabled';
|
|
30
|
+
this.max = _readMax(dom);
|
|
31
|
+
|
|
32
|
+
this.available = dom.querySelector('[' + LIST_ATTR + '="available"]');
|
|
33
|
+
this.selected = dom.querySelector('[' + LIST_ATTR + '="selected"]');
|
|
34
|
+
|
|
35
|
+
// Report the gap rather than failing on the first click.
|
|
36
|
+
if (!this.available || !this.selected) {
|
|
37
|
+
console.warn('[ln-picklist] requires both [' + LIST_ATTR + '="available"] and [' + LIST_ATTR + '="selected"]', dom);
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Bound once so destroy() can detach the same reference.
|
|
42
|
+
this._onChange = this._onChange.bind(this);
|
|
43
|
+
dom.addEventListener('change', this._onChange);
|
|
44
|
+
|
|
45
|
+
// Snapshot the authored items in document order.
|
|
46
|
+
this._initial = [];
|
|
47
|
+
for (const list of [this.available, this.selected]) {
|
|
48
|
+
for (const item of list.children) {
|
|
49
|
+
this._initial.push(item);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Initial sync: transfer checked items to selected, unchecked to available.
|
|
54
|
+
this.sync();
|
|
55
|
+
|
|
56
|
+
this._form = dom.closest('form');
|
|
57
|
+
if (this._form) {
|
|
58
|
+
this._onFormReset = this._onFormReset.bind(this);
|
|
59
|
+
this._form.addEventListener('reset', this._onFormReset);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ─── Lifecycle ─────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
_component.prototype.destroy = function () {
|
|
68
|
+
if (!this.dom[DOM_ATTRIBUTE]) return;
|
|
69
|
+
this._destroyed = true;
|
|
70
|
+
if (this._onChange) this.dom.removeEventListener('change', this._onChange);
|
|
71
|
+
if (this._form) this._form.removeEventListener('reset', this._onFormReset);
|
|
72
|
+
delete this.dom[DOM_ATTRIBUTE];
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// ─── Instance API ──────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
_component.prototype.enable = function () {
|
|
78
|
+
this.dom.setAttribute(DOM_SELECTOR, '');
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
_component.prototype.disable = function () {
|
|
82
|
+
this.dom.setAttribute(DOM_SELECTOR, 'disabled');
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
_component.prototype.sync = function () {
|
|
86
|
+
if (!this.available || !this.selected) return;
|
|
87
|
+
|
|
88
|
+
// Include any dynamically added items not yet tracked
|
|
89
|
+
const currentItems = Array.from(this.available.children).concat(Array.from(this.selected.children));
|
|
90
|
+
for (let i = 0; i < currentItems.length; i++) {
|
|
91
|
+
if (!this._initial.includes(currentItems[i])) {
|
|
92
|
+
this._initial.push(currentItems[i]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let selectedCount = 0;
|
|
97
|
+
for (let i = 0; i < this._initial.length; i++) {
|
|
98
|
+
const item = this._initial[i];
|
|
99
|
+
if (!item.isConnected) continue;
|
|
100
|
+
const checkbox = item.querySelector('input[type="checkbox"]');
|
|
101
|
+
if (!checkbox) continue;
|
|
102
|
+
|
|
103
|
+
let targetList;
|
|
104
|
+
if (checkbox.checked) {
|
|
105
|
+
if (this.max === null || selectedCount < this.max) {
|
|
106
|
+
targetList = this.selected;
|
|
107
|
+
selectedCount++;
|
|
108
|
+
} else {
|
|
109
|
+
checkbox.checked = false;
|
|
110
|
+
targetList = this.available;
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
targetList = this.available;
|
|
114
|
+
}
|
|
115
|
+
targetList.appendChild(item);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// ─── Form Reset ────────────────────────────────────────────
|
|
120
|
+
//
|
|
121
|
+
// Resetting a form restores every control to its default SILENTLY — the
|
|
122
|
+
// spec fires no `change` and no `input` for them, only `reset` on the form
|
|
123
|
+
// itself. Re-syncing in recorded order rebuilds both lists according to
|
|
124
|
+
// defaultChecked.
|
|
125
|
+
|
|
126
|
+
_component.prototype._onFormReset = function (e) {
|
|
127
|
+
const self = this;
|
|
128
|
+
|
|
129
|
+
// `reset` fires BEFORE the controls are restored, and it is cancelable,
|
|
130
|
+
// so the work is deferred and re-checked — the same shape ln-editor
|
|
131
|
+
// uses to re-read its textarea.
|
|
132
|
+
setTimeout(function () {
|
|
133
|
+
if (self._destroyed || e.defaultPrevented) return;
|
|
134
|
+
self.sync();
|
|
135
|
+
}, 0);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// ─── Change Handler ────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
_component.prototype._onChange = function (e) {
|
|
141
|
+
// `change` bubbles, so anything the author composes inside the root —
|
|
142
|
+
// an ln-search input, a select — reaches this listener. Filter hard.
|
|
143
|
+
const checkbox = e.target.closest('input[type="checkbox"]');
|
|
144
|
+
if (!checkbox) return;
|
|
145
|
+
|
|
146
|
+
const item = checkbox.closest('li');
|
|
147
|
+
if (!item) return;
|
|
148
|
+
|
|
149
|
+
const from = item.parentElement;
|
|
150
|
+
if (from !== this.available && from !== this.selected) return;
|
|
151
|
+
|
|
152
|
+
// The browser has already toggled the box by the time this runs, so a
|
|
153
|
+
// bare return would leave it checked while the item stays put — which
|
|
154
|
+
// is exactly the contradiction this component exists to avoid.
|
|
155
|
+
if (!this.isEnabled) {
|
|
156
|
+
checkbox.checked = !checkbox.checked;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const to = checkbox.checked ? this.selected : this.available;
|
|
161
|
+
|
|
162
|
+
// Inconsistent authored markup (a checked item rendered on the left),
|
|
163
|
+
// or a synthetic change that did not flip the box, would otherwise
|
|
164
|
+
// re-append in place and emit a move that never happened.
|
|
165
|
+
if (from === to) return;
|
|
166
|
+
|
|
167
|
+
// Enforce maximum selection limit if configured
|
|
168
|
+
if (to === this.selected && this.max !== null && this.selected.children.length >= this.max) {
|
|
169
|
+
checkbox.checked = !checkbox.checked;
|
|
170
|
+
dispatch(this.dom, 'ln-picklist:max-reached', {
|
|
171
|
+
max: this.max,
|
|
172
|
+
item: item,
|
|
173
|
+
checkbox: checkbox,
|
|
174
|
+
count: this.selected.children.length
|
|
175
|
+
});
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// One record, both events — they describe the same move.
|
|
180
|
+
const detail = { item: item, from: from, to: to, checkbox: checkbox };
|
|
181
|
+
|
|
182
|
+
if (dispatchCancelable(this.dom, 'ln-picklist:before-move', detail).defaultPrevented) {
|
|
183
|
+
checkbox.checked = !checkbox.checked;
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Re-parenting a node that holds focus blurs it to <body> in Chromium.
|
|
188
|
+
// Only restore when the focus really was here: a synthetic change from
|
|
189
|
+
// a script must not steal focus away from whatever the user is using.
|
|
190
|
+
const hadFocus = document.activeElement === checkbox;
|
|
191
|
+
|
|
192
|
+
to.appendChild(item);
|
|
193
|
+
|
|
194
|
+
if (hadFocus) checkbox.focus();
|
|
195
|
+
|
|
196
|
+
dispatch(this.dom, 'ln-picklist:move', detail);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// ─── Attribute Sync ────────────────────────────────────────
|
|
200
|
+
|
|
201
|
+
function _readMax(el) {
|
|
202
|
+
const raw = el.getAttribute(MAX_ATTR);
|
|
203
|
+
if (raw === null || raw === '') return null;
|
|
204
|
+
const parsed = parseInt(raw, 10);
|
|
205
|
+
return isNaN(parsed) || parsed < 0 ? null : parsed;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function _syncEnabled(el) {
|
|
209
|
+
const instance = el[DOM_ATTRIBUTE];
|
|
210
|
+
if (!instance) return;
|
|
211
|
+
const shouldBeEnabled = el.getAttribute(DOM_SELECTOR) !== 'disabled';
|
|
212
|
+
if (shouldBeEnabled === instance.isEnabled) return;
|
|
213
|
+
instance.isEnabled = shouldBeEnabled;
|
|
214
|
+
dispatch(el, shouldBeEnabled ? 'ln-picklist:enabled' : 'ln-picklist:disabled', { target: el });
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function _syncMax(el) {
|
|
218
|
+
const instance = el[DOM_ATTRIBUTE];
|
|
219
|
+
if (!instance) return;
|
|
220
|
+
instance.max = _readMax(el);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ─── Init ──────────────────────────────────────────────────
|
|
224
|
+
|
|
225
|
+
registerComponent(DOM_SELECTOR, DOM_ATTRIBUTE, _component, 'ln-picklist', {
|
|
226
|
+
attributes: ATTRIBUTES
|
|
227
|
+
});
|
|
228
|
+
})();
|
|
@@ -1,162 +1,164 @@
|
|
|
1
|
-
# ln-popover
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
</
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
- **
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- `data-ln-popover
|
|
69
|
-
- `data-ln-popover-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
|
80
|
-
|
|
81
|
-
| **`ln-popover:before-
|
|
82
|
-
| **`ln-popover:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
`
|
|
1
|
+
# ln-popover
|
|
2
|
+
|
|
3
|
+
> Applied to a container via `data-ln-popover id="..."`, paired with a `<button data-ln-popover-for="...">`.
|
|
4
|
+
> On trigger `click`, it sets `popover="manual"` on the container, calls `showPopover()`, sets inline `top`/`left` coordinates, and writes `data-ln-popover="open"`.
|
|
5
|
+
> On outside `click` or `Escape`, it calls `hidePopover()` and writes `data-ln-popover="closed"`.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Philosophy & Mindset
|
|
10
|
+
|
|
11
|
+
In `ln-ashlar`, the core design principle is **orthogonality**. Rather than creating a heavy component that bundles state, positioning algorithms, LIFO click stacks, and styles, `ln-popover` splits them cleanly:
|
|
12
|
+
|
|
13
|
+
1. **State & Positioning (JavaScript + native Popover API)**: The `ln-popover` script handles binary `open` / `closed` states in the DOM, bridged to the native Popover API (`popover="manual"`, `showPopover()`/`hidePopover()`) purely for top-layer rendering — no ancestor `overflow`/`z-index` can clip or bury it. Because `manual` mode has no native light-dismiss, the script still owns 100% of the behavior: viewport-boundary flip placement, keyboard focus save/restore, and the LIFO (Last-In, First-Out) ESC dismissal stack.
|
|
14
|
+
2. **Visual Presentation (CSS)**: Visual layouts, background shadows, and borders are handled in Vanilla CSS. The library ships a premium `@mixin popover` to style popover cards.
|
|
15
|
+
3. **Trigger decoupling (HTML)**: Triggers (`data-ln-popover-for="popoverId"`) and popover containers (`id="popoverId"`) are bound purely by ID, allowing the trigger button and the popup card to live anywhere in the document.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 2. Minimal Blueprint
|
|
20
|
+
|
|
21
|
+
Triggers and popovers are paired by ID. Wrap content in a `div` carrying the `data-ln-popover` attribute.
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<!-- Trigger anywhere -->
|
|
25
|
+
<button data-ln-popover-for="account-menu">Account</button>
|
|
26
|
+
|
|
27
|
+
<!-- Popover anywhere — role="dialog", tabindex="-1", and popover="manual" are injected automatically -->
|
|
28
|
+
<div data-ln-popover id="account-menu">
|
|
29
|
+
<p><strong>user@example.com</strong></p>
|
|
30
|
+
<nav>
|
|
31
|
+
<a href="/settings">Settings</a>
|
|
32
|
+
<a href="/logout">Sign out</a>
|
|
33
|
+
</nav>
|
|
34
|
+
</div>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Key Anatomy Rules
|
|
38
|
+
- **The Popover wrapper (`data-ln-popover`)**: Driven by the value `"open"` (open) and `"closed"` or empty (closed).
|
|
39
|
+
- **The Trigger (`data-ln-popover-for="id"`)**: Sets `aria-expanded` and manages focus automatically.
|
|
40
|
+
- **Visual styling**: Re-apply `@mixin popover` in your SCSS on the popover element.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 3. Declarative API & State Contract
|
|
45
|
+
|
|
46
|
+
The initialized instance is exposed as `dom.lnPopover`, with `open(trigger)`, `close()`, `toggle(trigger)`, and `destroy()` methods, plus `isOpen` and `trigger` properties. **The HTML attribute remains the primary contract** — the instance methods are thin wrappers that ultimately write the same attribute.
|
|
47
|
+
|
|
48
|
+
Triggers, LIFO click outside handlers, viewport edge flips, and custom scripts all change state by writing the active attribute on the popover element:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
const popover = document.getElementById('account-menu');
|
|
52
|
+
|
|
53
|
+
// Open the popover
|
|
54
|
+
popover.setAttribute('data-ln-popover', 'open');
|
|
55
|
+
|
|
56
|
+
// Close the popover
|
|
57
|
+
popover.setAttribute('data-ln-popover', 'closed');
|
|
58
|
+
|
|
59
|
+
// Equivalent imperative calls via the instance
|
|
60
|
+
popover.lnPopover.open();
|
|
61
|
+
popover.lnPopover.close();
|
|
62
|
+
|
|
63
|
+
// Read-only state query
|
|
64
|
+
popover.lnPopover.isOpen; // Returns true/false
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Attributes
|
|
68
|
+
- `data-ln-popover`: Placed on the popover card. Value `"open"` = open; `"closed"` = closed.
|
|
69
|
+
- `data-ln-popover-for="id"`: Placed on triggers referencing the popover ID.
|
|
70
|
+
- `data-ln-popover-position="top|bottom|left|right"`: Preferred placement side. Default: `bottom`.
|
|
71
|
+
- `data-ln-popover-placement`: Set automatically by JS to indicate the *actual* active side after auto-flip is resolved.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 4. Transition Events
|
|
76
|
+
|
|
77
|
+
All events bubble. The dispatch target is the popover element itself.
|
|
78
|
+
|
|
79
|
+
| Event | Cancelable | `detail` | Dispatched When |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| **`ln-popover:before-open`** | **Yes** | `{ popoverId, target, trigger }` | Before opening. `event.preventDefault()` cancels the transition and reverts the attribute. |
|
|
82
|
+
| **`ln-popover:open`** | No | `{ popoverId, target, trigger }` | After popover is positioned, classes added, and focus moved. |
|
|
83
|
+
| **`ln-popover:before-close`** | **Yes** | `{ popoverId, target, trigger }` | Before closing. `event.preventDefault()` cancels the close and reverts the attribute. |
|
|
84
|
+
| **`ln-popover:close`** | No | `{ popoverId, target, trigger }` | After popover is closed and focus restored back to the trigger. |
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
// Example: Cancel open transition for unauthorized zones
|
|
88
|
+
document.addEventListener('ln-popover:before-open', (e) => {
|
|
89
|
+
if (e.detail.popoverId === 'admin-zone' && !currentUser.isAdmin) {
|
|
90
|
+
e.preventDefault(); // Reverts attribute back to "closed"
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 5. Integration Patterns
|
|
98
|
+
|
|
99
|
+
### A. Position Preferences & Auto-Flip
|
|
100
|
+
Preferred placement is easily configured. If there isn't enough room in the viewport, the positioning engine flips the popover to the opposite side:
|
|
101
|
+
```html
|
|
102
|
+
<div data-ln-popover data-ln-popover-position="right" id="help-menu">...</div>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### B. Nested Popovers (A stays open when B opens)
|
|
106
|
+
Opening B from inside A leaves A open. Pressing `ESC` once closes B first, and then A:
|
|
107
|
+
```html
|
|
108
|
+
<div data-ln-popover id="popover-a">
|
|
109
|
+
<button data-ln-popover-for="popover-b">Open B</button>
|
|
110
|
+
</div>
|
|
111
|
+
<div data-ln-popover id="popover-b">...</div>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 6. Integration & Source Files
|
|
117
|
+
|
|
118
|
+
- **Unified Bundle**: Loaded automatically with the main bundle:
|
|
119
|
+
```html
|
|
120
|
+
<script src="dist/ln-ashlar.iife.js" defer></script>
|
|
121
|
+
```
|
|
122
|
+
- **Standalone IIFE**: For lightweight pages, load the standalone, self-registering IIFE version:
|
|
123
|
+
```html
|
|
124
|
+
<script src="components/ln-popover/ln-popover.js" defer></script>
|
|
125
|
+
```
|
|
126
|
+
- **Active Source (ESM)**: Development source is located at [components/ln-popover/src/ln-popover.js](file:///c:/laragon/www/ln-ashlar/components/ln-popover/src/ln-popover.js).
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Related
|
|
131
|
+
- **[`ln-dropdown`](../ln-dropdown/README.md)** — Menu wrapper adding click-outside/top-layer promotion.
|
|
132
|
+
- **[`ln-toggle`](../ln-toggle/README.md)** — Binary disclosure state primitive.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 🔧 Internals
|
|
137
|
+
|
|
138
|
+
Source: `components/ln-popover/ln-popover.js`.
|
|
139
|
+
|
|
140
|
+
### Open-stack
|
|
141
|
+
|
|
142
|
+
A module-level `openStack` array tracks all currently-open instances. It drives two behaviors: a single `document` `keydown` listener, registered only while the stack is non-empty, pops the top entry and calls `.close()` on it (LIFO Escape); and nested popovers stay independent because each owns its own outside-click listener scoped to its own subtree.
|
|
143
|
+
|
|
144
|
+
### `_applyOpen(trigger)` — after the cancelable `before-open` passes
|
|
145
|
+
|
|
146
|
+
Set `isOpen = true`, store `trigger` (`null` if opened via direct attribute mutation) and `document.activeElement` (for focus restore) → promotes the element to the top layer via `showPopover()` (so `position: fixed` coordinates are reliable regardless of ancestor `transform`, `contain`, or `overflow: hidden`) → `measureHidden(dom)` for dimensions even if `display: none` → `computePlacement(triggerRect, size, preferred, 8)` writes `top`/`left` inline (unavoidable for floating UI) and `data-ln-popover-placement` → `aria-expanded="true"` on trigger → focus the first focusable child, or the container itself → outside-click listener registered one tick later via `setTimeout` (so the opening click itself doesn't immediately close it) → scroll/resize listeners for repositioning while open → push onto `openStack`, ensure ESC listener → dispatch `ln-popover:open`.
|
|
147
|
+
|
|
148
|
+
### `_applyClose()` — mirror of `_applyOpen`
|
|
149
|
+
|
|
150
|
+
Clears `isOpen`, removes the outside-click/scroll/resize listeners, clears inline `top`/`left` and the placement attribute, sets `aria-expanded="false"`, exits the top layer via `hidePopover()`, splices itself from `openStack` (removing the ESC listener if the stack is now empty), then restores focus to the trigger **only if** the trigger was the previously-focused element (click→Escape, click→programmatic close) or `activeElement === document.body` (Escape from inside the popover, outside-click on inert whitespace) — an outside-click landing on another focusable element keeps that element's focus. Dispatches `ln-popover:close`.
|
|
151
|
+
|
|
152
|
+
### Focus management
|
|
153
|
+
|
|
154
|
+
A disclosure pattern, not a modal — no Tab trap. Because the popover is promoted to the top layer purely for rendering, it remains in its authored DOM position, so Tab order follows the markup rather than jumping to the end of `<body>`. `tabindex="-1"` and `role="dialog"` are set automatically at construction so the container itself is a valid focus target when there's no focusable child.
|
|
155
|
+
|
|
156
|
+
### Nested popovers
|
|
157
|
+
|
|
158
|
+
Outside-click tests `self.dom.contains(e.target)`, so a click inside A's subtree (including a button that opens B) never triggers A's close path. Both popovers land on `openStack`; LIFO Escape closes B first, then A on the next press. There is no "close all."
|
|
159
|
+
|
|
160
|
+
### Observer & registration
|
|
161
|
+
|
|
162
|
+
Two separate `registerComponent` calls wire popover elements (`el.lnPopover`) and trigger elements (`el.lnPopoverTrigger`) independently — `registerComponent` handles DOM discovery and lifecycle. On attribute mutations to `data-ln-popover`, `registerComponent`'s `onAttributeChange` callback evaluates open/closed transitions and dispatches `before-open` / `before-close` events. Trigger init sets `aria-haspopup="dialog"`, `aria-expanded="false"`, and `aria-controls` once on attach.
|
|
163
|
+
|
|
164
|
+
`destroy()` on a popover instance closes it if open, removes its listeners, and splices it from `openStack`. Trigger `destroy` is independent and only removes the trigger's click handler.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
@use '../../theme/config/mixins' as *;
|
|
2
|
+
|
|
3
|
+
[data-ln-debug] {
|
|
4
|
+
// 1. Popover Missing ID: popovers controlled by data-ln-popover must have an id for trigger linking
|
|
5
|
+
[data-ln-popover]:not([id]) {
|
|
6
|
+
@include dev-dom-error("[data-ln-popover] is missing a required 'id' attribute for trigger linking.");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// 2. Popover Trigger Empty ID: trigger elements must point to a target popover ID
|
|
10
|
+
[data-ln-popover-for=""] {
|
|
11
|
+
@include dev-inline-error("data-ln-popover-for target ID cannot be empty");
|
|
12
|
+
}
|
|
13
|
+
}
|