@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,213 +1,247 @@
|
|
|
1
|
-
// ─── Windowed Sparse Cache ─────────────────────────────────
|
|
2
|
-
//
|
|
3
|
-
// DOM-agnostic sliding-window data engine for server-side virtualization.
|
|
4
|
-
// Owns a sparse cache keyed by logical index, logical/grand totals, request
|
|
5
|
-
// dedup, a stale-guard via queryGen, LRU eviction to a bounded cap, and a
|
|
6
|
-
// debounced fetch trigger. Transport-agnostic: the consumer supplies
|
|
7
|
-
// requestPage() (kick a fetch — any transport) and onChange() (cache mutated,
|
|
8
|
-
// re-render). Render clients pull rows via get()/has() and read logicalTotal
|
|
9
|
-
// for spacer geometry; they hold no cache of their own. Shared by the ln-table
|
|
10
|
-
// and ln-list windowed paths; a future ln-data-store windowed mode plugs in by
|
|
11
|
-
// making requestPage resolve getAll({offset,limit}) then call ingest().
|
|
12
|
-
|
|
13
|
-
export function createWindowCache(config) {
|
|
14
|
-
config = config || {};
|
|
15
|
-
let windowSize = config.windowSize > 0 ? config.windowSize : 1000;
|
|
16
|
-
let pageSize = config.pageSize > 0 ? config.pageSize : 200;
|
|
17
|
-
let threshold = config.threshold != null ? config.threshold : 25;
|
|
18
|
-
let fetchDebounce = config.fetchDebounce != null ? config.fetchDebounce : 120;
|
|
19
|
-
const requestPage = typeof config.requestPage === 'function' ? config.requestPage : function () {};
|
|
20
|
-
const onChange = typeof config.onChange === 'function' ? config.onChange : function () {};
|
|
21
|
-
|
|
22
|
-
const map = new Map(); // logicalIndex → record
|
|
23
|
-
const touch = new Map(); // logicalIndex → seq (LRU stamp)
|
|
24
|
-
const inflight = new Set(); // offsets currently requested (dedup)
|
|
25
|
-
let logicalTotal = 0;
|
|
26
|
-
let grandTotal = 0;
|
|
27
|
-
let queryGen = 0;
|
|
28
|
-
let query = { sort: null, filters: {}, search: '' };
|
|
29
|
-
let debounceId = null;
|
|
30
|
-
let seq = 0;
|
|
31
|
-
let lastRangeStart = 0; // last ensure() visible range — revalidate() re-targets here, not page 0
|
|
32
|
-
let lastRangeEnd = 0;
|
|
33
|
-
let pendingSwap = false; // set by invalidate()/revalidate(), consumed by the new generation's first ingest()
|
|
34
|
-
|
|
35
|
-
function stamp(i) { touch.set(i, ++seq); }
|
|
36
|
-
|
|
37
|
-
function hasActiveQuery() {
|
|
38
|
-
return !!(query && (query.search || (query.filters && Object.keys(query.filters).length)));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function evict() {
|
|
42
|
-
if (map.size <= windowSize) return;
|
|
43
|
-
// LRU: drop least-recently touched/requested rows first
|
|
44
|
-
const keys = Array.from(map.keys()).sort(function (a, b) {
|
|
45
|
-
return (touch.get(a) || 0) - (touch.get(b) || 0);
|
|
46
|
-
});
|
|
47
|
-
let i = 0;
|
|
48
|
-
while (map.size > windowSize && i < keys.length) {
|
|
49
|
-
map.delete(keys[i]);
|
|
50
|
-
touch.delete(keys[i]);
|
|
51
|
-
i++;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function fire(offset, limit) {
|
|
56
|
-
inflight.add(offset);
|
|
57
|
-
requestPage(query, offset, limit);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
get: function (i) { return map.get(i); },
|
|
62
|
-
has: function (i) { return map.has(i); },
|
|
63
|
-
peek: function () { return map.size ? map.values().next().value : undefined; },
|
|
64
|
-
|
|
65
|
-
get logicalTotal() { return logicalTotal; },
|
|
66
|
-
get grandTotal() { return grandTotal; },
|
|
67
|
-
get queryGen() { return queryGen; },
|
|
68
|
-
get size() { return map.size; },
|
|
69
|
-
|
|
70
|
-
// Render client hands its visible logical range; stamps in-range resident
|
|
71
|
-
// rows as freshly used, then checks if any page in range (padded by threshold)
|
|
72
|
-
// is missing from cache and needs to be fetched (page-aligned).
|
|
73
|
-
ensure: function (startRow, endRow) {
|
|
74
|
-
clearTimeout(debounceId);
|
|
75
|
-
lastRangeStart = startRow;
|
|
76
|
-
lastRangeEnd = endRow;
|
|
77
|
-
for (let i = startRow; i < endRow; i++) {
|
|
78
|
-
if (map.has(i)) stamp(i);
|
|
79
|
-
}
|
|
80
|
-
if (logicalTotal <= 0) return;
|
|
81
|
-
|
|
82
|
-
const checkStart = Math.max(0, startRow - threshold);
|
|
83
|
-
const checkEnd = Math.min(logicalTotal, endRow + threshold);
|
|
84
|
-
|
|
85
|
-
const firstPage = Math.floor(checkStart / pageSize);
|
|
86
|
-
const lastPage = Math.floor(Math.max(0, checkEnd - 1) / pageSize);
|
|
87
|
-
|
|
88
|
-
let targetPageOffset = -1;
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
1
|
+
// ─── Windowed Sparse Cache ─────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// DOM-agnostic sliding-window data engine for server-side virtualization.
|
|
4
|
+
// Owns a sparse cache keyed by logical index, logical/grand totals, request
|
|
5
|
+
// dedup, a stale-guard via queryGen, LRU eviction to a bounded cap, and a
|
|
6
|
+
// debounced fetch trigger. Transport-agnostic: the consumer supplies
|
|
7
|
+
// requestPage() (kick a fetch — any transport) and onChange() (cache mutated,
|
|
8
|
+
// re-render). Render clients pull rows via get()/has() and read logicalTotal
|
|
9
|
+
// for spacer geometry; they hold no cache of their own. Shared by the ln-table
|
|
10
|
+
// and ln-list windowed paths; a future ln-data-store windowed mode plugs in by
|
|
11
|
+
// making requestPage resolve getAll({offset,limit}) then call ingest().
|
|
12
|
+
|
|
13
|
+
export function createWindowCache(config) {
|
|
14
|
+
config = config || {};
|
|
15
|
+
let windowSize = config.windowSize > 0 ? config.windowSize : 1000;
|
|
16
|
+
let pageSize = config.pageSize > 0 ? config.pageSize : 200;
|
|
17
|
+
let threshold = config.threshold != null ? config.threshold : 25;
|
|
18
|
+
let fetchDebounce = config.fetchDebounce != null ? config.fetchDebounce : 120;
|
|
19
|
+
const requestPage = typeof config.requestPage === 'function' ? config.requestPage : function () {};
|
|
20
|
+
const onChange = typeof config.onChange === 'function' ? config.onChange : function () {};
|
|
21
|
+
|
|
22
|
+
const map = new Map(); // logicalIndex → record
|
|
23
|
+
const touch = new Map(); // logicalIndex → seq (LRU stamp)
|
|
24
|
+
const inflight = new Set(); // offsets currently requested (dedup)
|
|
25
|
+
let logicalTotal = 0;
|
|
26
|
+
let grandTotal = 0;
|
|
27
|
+
let queryGen = 0;
|
|
28
|
+
let query = { sort: null, filters: {}, search: '' };
|
|
29
|
+
let debounceId = null;
|
|
30
|
+
let seq = 0;
|
|
31
|
+
let lastRangeStart = 0; // last ensure() visible range — revalidate() re-targets here, not page 0
|
|
32
|
+
let lastRangeEnd = 0;
|
|
33
|
+
let pendingSwap = false; // set by invalidate()/revalidate(), consumed by the new generation's first ingest()
|
|
34
|
+
|
|
35
|
+
function stamp(i) { touch.set(i, ++seq); }
|
|
36
|
+
|
|
37
|
+
function hasActiveQuery() {
|
|
38
|
+
return !!(query && (query.search || (query.filters && Object.keys(query.filters).length)));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function evict() {
|
|
42
|
+
if (map.size <= windowSize) return;
|
|
43
|
+
// LRU: drop least-recently touched/requested rows first
|
|
44
|
+
const keys = Array.from(map.keys()).sort(function (a, b) {
|
|
45
|
+
return (touch.get(a) || 0) - (touch.get(b) || 0);
|
|
46
|
+
});
|
|
47
|
+
let i = 0;
|
|
48
|
+
while (map.size > windowSize && i < keys.length) {
|
|
49
|
+
map.delete(keys[i]);
|
|
50
|
+
touch.delete(keys[i]);
|
|
51
|
+
i++;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function fire(offset, limit) {
|
|
56
|
+
inflight.add(offset);
|
|
57
|
+
requestPage(query, offset, limit);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
get: function (i) { return map.get(i); },
|
|
62
|
+
has: function (i) { return map.has(i); },
|
|
63
|
+
peek: function () { return map.size ? map.values().next().value : undefined; },
|
|
64
|
+
|
|
65
|
+
get logicalTotal() { return logicalTotal; },
|
|
66
|
+
get grandTotal() { return grandTotal; },
|
|
67
|
+
get queryGen() { return queryGen; },
|
|
68
|
+
get size() { return map.size; },
|
|
69
|
+
|
|
70
|
+
// Render client hands its visible logical range; stamps in-range resident
|
|
71
|
+
// rows as freshly used, then checks if any page in range (padded by threshold)
|
|
72
|
+
// is missing from cache and needs to be fetched (page-aligned).
|
|
73
|
+
ensure: function (startRow, endRow) {
|
|
74
|
+
clearTimeout(debounceId);
|
|
75
|
+
lastRangeStart = startRow;
|
|
76
|
+
lastRangeEnd = endRow;
|
|
77
|
+
for (let i = startRow; i < endRow; i++) {
|
|
78
|
+
if (map.has(i)) stamp(i);
|
|
79
|
+
}
|
|
80
|
+
if (logicalTotal <= 0) return;
|
|
81
|
+
|
|
82
|
+
const checkStart = Math.max(0, startRow - threshold);
|
|
83
|
+
const checkEnd = Math.min(logicalTotal, endRow + threshold);
|
|
84
|
+
|
|
85
|
+
const firstPage = Math.floor(checkStart / pageSize);
|
|
86
|
+
const lastPage = Math.floor(Math.max(0, checkEnd - 1) / pageSize);
|
|
87
|
+
|
|
88
|
+
let targetPageOffset = -1;
|
|
89
|
+
|
|
90
|
+
for (let p = firstPage; p <= lastPage; p++) {
|
|
91
|
+
const pOffset = p * pageSize;
|
|
92
|
+
// Bounds the missing-row scan only — the request always asks for a
|
|
93
|
+
// full page. logicalTotal is a stale carry-over between invalidate()
|
|
94
|
+
// and the new generation's first ingest(); clamping the limit by it
|
|
95
|
+
// short-fetches the page and costs a second request for the same offset.
|
|
96
|
+
const pLimit = Math.min(pageSize, logicalTotal - pOffset);
|
|
97
|
+
|
|
98
|
+
let hasMissing = false;
|
|
99
|
+
const pageCheckStart = Math.max(pOffset, checkStart);
|
|
100
|
+
const pageCheckEnd = Math.min(pOffset + pLimit, checkEnd);
|
|
101
|
+
for (let i = pageCheckStart; i < pageCheckEnd; i++) {
|
|
102
|
+
if (!map.has(i)) {
|
|
103
|
+
hasMissing = true;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (hasMissing && !inflight.has(pOffset)) {
|
|
109
|
+
targetPageOffset = pOffset;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (targetPageOffset === -1) return;
|
|
115
|
+
|
|
116
|
+
debounceId = setTimeout(function () {
|
|
117
|
+
fire(targetPageOffset, pageSize);
|
|
118
|
+
}, fetchDebounce);
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
// Splice a fetched page. Stale (superseded-query) responses are dropped.
|
|
122
|
+
// Out-of-order pages splice at their own offset, so order is irrelevant.
|
|
123
|
+
// Returns whether the page counted as an answer — the render client keys
|
|
124
|
+
// its loading affordance off that.
|
|
125
|
+
ingest: function (detail) {
|
|
126
|
+
detail = detail || {};
|
|
127
|
+
if (detail.queryGen != null && detail.queryGen !== queryGen) return false;
|
|
128
|
+
|
|
129
|
+
const offset = detail.offset || 0;
|
|
130
|
+
const rows = detail.data || [];
|
|
131
|
+
let resolved = 0;
|
|
132
|
+
for (let i = 0; i < rows.length; i++) {
|
|
133
|
+
if (rows[i] != null) resolved++;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// A page that resolved nothing is not an answer in two cases. A windowed
|
|
137
|
+
// store whose position index was just reset answers the next request with
|
|
138
|
+
// pure nulls and a carried-over filtered count; and a provisional page
|
|
139
|
+
// states rows only, so an empty one states nothing at all. Letting either
|
|
140
|
+
// through consumes the swap below and blanks the view — the exact flash
|
|
141
|
+
// stale-while-revalidate exists to prevent. An authoritative filtered === 0
|
|
142
|
+
// is a different statement: the source declaring an empty result set, which
|
|
143
|
+
// must render the empty state.
|
|
144
|
+
if (resolved === 0 && (detail.provisional || detail.filtered > 0)) {
|
|
145
|
+
inflight.delete(offset);
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// First response of a new generation: drop the stale rows now, at the
|
|
150
|
+
// swap moment, not at invalidate()/revalidate() time — stale-while-revalidate.
|
|
151
|
+
if (pendingSwap) {
|
|
152
|
+
map.clear();
|
|
153
|
+
touch.clear();
|
|
154
|
+
pendingSwap = false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// A provisional page carries rows, not totals. Knowing how many records
|
|
158
|
+
// match requires looking at every one of them, which is exactly the work
|
|
159
|
+
// the local answer skips to stay fast — so the counts and the spacer
|
|
160
|
+
// geometry hold at whatever the last authoritative answer established.
|
|
161
|
+
if (!detail.provisional) {
|
|
162
|
+
grandTotal = detail.total != null ? detail.total : grandTotal;
|
|
163
|
+
logicalTotal = detail.filtered != null
|
|
164
|
+
? detail.filtered
|
|
165
|
+
: (detail.data ? detail.data.length : logicalTotal);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
for (let i = 0; i < rows.length; i++) {
|
|
169
|
+
// A windowed source sends null for a position it has not resolved
|
|
170
|
+
// yet. That is absence, not a record — keeping it out of the map is
|
|
171
|
+
// what makes has() honest and renders a placeholder instead.
|
|
172
|
+
if (rows[i] == null) continue;
|
|
173
|
+
map.set(offset + i, rows[i]);
|
|
174
|
+
stamp(offset + i);
|
|
175
|
+
}
|
|
176
|
+
inflight.delete(offset);
|
|
177
|
+
evict();
|
|
178
|
+
onChange();
|
|
179
|
+
return true;
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
// First load: fetch page 0 at the current generation (no bump).
|
|
183
|
+
requestInitial: function (q) {
|
|
184
|
+
if (q) query = q;
|
|
185
|
+
fire(0, pageSize);
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
// Query change: new generation, stale rows stay visible until the first
|
|
189
|
+
// response of the new generation lands in ingest() — no blanking, no
|
|
190
|
+
// placeholder flash (ln-table--loading is the refresh affordance).
|
|
191
|
+
invalidate: function (q) {
|
|
192
|
+
queryGen++;
|
|
193
|
+
inflight.clear();
|
|
194
|
+
clearTimeout(debounceId);
|
|
195
|
+
if (q) query = q;
|
|
196
|
+
pendingSwap = true;
|
|
197
|
+
fire(0, pageSize);
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
// Post-mutation refresh of a windowed view: same stale-while-revalidate
|
|
201
|
+
// swap as invalidate(), but re-requests the page at the CURRENT scroll
|
|
202
|
+
// position instead of jumping back to page 0.
|
|
203
|
+
revalidate: function () {
|
|
204
|
+
queryGen++;
|
|
205
|
+
inflight.clear();
|
|
206
|
+
clearTimeout(debounceId);
|
|
207
|
+
pendingSwap = true;
|
|
208
|
+
const offset = Math.max(0, Math.floor(lastRangeStart / pageSize) * pageSize);
|
|
209
|
+
fire(offset, pageSize);
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
// Failed page fetch: release the offset so the next ensure() (scroll,
|
|
213
|
+
// filter, resize) can re-request it. No onChange(), no auto-retry.
|
|
214
|
+
release: function (offset) {
|
|
215
|
+
inflight.delete(offset);
|
|
216
|
+
},
|
|
217
|
+
|
|
218
|
+
destroy: function () {
|
|
219
|
+
clearTimeout(debounceId);
|
|
220
|
+
map.clear();
|
|
221
|
+
touch.clear();
|
|
222
|
+
inflight.clear();
|
|
223
|
+
},
|
|
224
|
+
|
|
225
|
+
configure: function (partial) {
|
|
226
|
+
partial = partial || {};
|
|
227
|
+
let geometryChanged = false;
|
|
228
|
+
if (partial.windowSize != null && partial.windowSize > 0 && partial.windowSize !== windowSize) {
|
|
229
|
+
const shrank = partial.windowSize < windowSize;
|
|
230
|
+
windowSize = partial.windowSize;
|
|
231
|
+
if (shrank) evict();
|
|
232
|
+
geometryChanged = true;
|
|
233
|
+
}
|
|
234
|
+
if (partial.pageSize != null && partial.pageSize > 0) pageSize = partial.pageSize;
|
|
235
|
+
if (partial.threshold != null && partial.threshold >= 0) threshold = partial.threshold;
|
|
236
|
+
if (partial.fetchDebounce != null && partial.fetchDebounce >= 0) fetchDebounce = partial.fetchDebounce;
|
|
237
|
+
if (geometryChanged) onChange();
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
setGrandTotal: function (n) {
|
|
241
|
+
if (n == null || isNaN(n) || n < 0) return;
|
|
242
|
+
grandTotal = n;
|
|
243
|
+
if (!hasActiveQuery()) logicalTotal = n;
|
|
244
|
+
onChange();
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# `data-ln-couchdb-connector`
|
|
2
2
|
|
|
3
|
+
> Applied to a gateway element (`<div data-ln-couchdb-connector data-ln-couchdb-url="..." data-ln-couchdb-db="...">`) inside a coordinator. It listens for database request CustomEvents (`ln-couchdb-connector:request-sync`, `create`, `update`, `delete`, `bulk-delete`), queries CouchDB `_changes` feeds with sequence tokens for delta sync, and maps `id` to `_id`/`_rev` on mutations via REST `fetch()`. Upon resolution, it emits `ln-couchdb-connector:fetched` or mutation response events to the parent coordinator.
|
|
4
|
+
|
|
3
5
|
A zero-dependency, Local-First sync transport component that implements the Transport Gateway pattern of `ln-ashlar` for CouchDB and Sync Gateway instances.
|
|
4
6
|
|
|
5
7
|
This component encapsulates all connection parameters (CouchDB base URL, database name, auth credentials, headers) and provides a declarative, event-driven, or programmatic way to talk to any CouchDB-compatible backend using standard Changes Feed (`_changes`) protocols. It isolates networking concerns completely, making your cache store (`data-ln-data-store`) and visual presentation layers fully network-agnostic.
|
|
@@ -35,8 +37,8 @@ All attributes are dynamically observed. Any runtime changes to these attributes
|
|
|
35
37
|
| Attribute | Category | Description |
|
|
36
38
|
|-----------|----------|-------------|
|
|
37
39
|
| `data-ln-couchdb-connector` | Selector | Creates the component instance. |
|
|
38
|
-
| `data-ln-couchdb-url` | Connection | The base URL of the CouchDB Server or Sync Gateway (e.g. `https://couch.example.com`).
|
|
39
|
-
| `data-ln-couchdb-db` | Connection | Database name endpoint (e.g. `tasks`).
|
|
40
|
+
| `data-ln-couchdb-url` | Connection | The base URL of the CouchDB Server or Sync Gateway (e.g. `https://couch.example.com`). |
|
|
41
|
+
| `data-ln-couchdb-db` | Connection | Database name endpoint (e.g. `tasks`). |
|
|
40
42
|
| `data-ln-couchdb-auth` | Credentials | Authorization header value (e.g. `Basic dXNlcjpwYXNz` or standard token). |
|
|
41
43
|
| `data-ln-couchdb-headers` | Credentials | JSON-formatted string of custom request headers. |
|
|
42
44
|
|
|
@@ -81,7 +83,7 @@ connector.bulkDelete(["doc_17", "doc_23"])
|
|
|
81
83
|
|
|
82
84
|
### Commands (Dispatched TO the connector)
|
|
83
85
|
|
|
84
|
-
You can trigger mutations and fetches asynchronously by dispatching standard events directly on the connector DOM element.
|
|
86
|
+
You can trigger mutations and fetches asynchronously by dispatching standard events directly on the connector DOM element.
|
|
85
87
|
|
|
86
88
|
| Event | `detail` Payload | Description |
|
|
87
89
|
|-------|------------------|-------------|
|
|
@@ -141,7 +143,7 @@ Here is how a parent Coordinator links a Cache Store and the CouchDB Connector u
|
|
|
141
143
|
// }));
|
|
142
144
|
// });
|
|
143
145
|
//
|
|
144
|
-
// See
|
|
146
|
+
// See components/ln-data-coordinator/README.md for the full fan-out + error
|
|
145
147
|
// reconciliation policy (auth/transient/deterministic) that ships with
|
|
146
148
|
// the coordinator — this connector never needs to be wired by hand.
|
|
147
149
|
})();
|
|
@@ -151,7 +153,7 @@ Here is how a parent Coordinator links a Cache Store and the CouchDB Connector u
|
|
|
151
153
|
|
|
152
154
|
## 🔧 Internals
|
|
153
155
|
|
|
154
|
-
Source: `
|
|
156
|
+
Source: `components/ln-couchdb-connector/*`. Bridges CouchDB's revision-based (`_rev`) document protocol and `_changes`/`_bulk_docs` endpoints to the same coordinator-facing event contract as `ln-api-connector`.
|
|
155
157
|
|
|
156
158
|
### Sync flow
|
|
157
159
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){"use strict";function B(){return typeof window>"u"?!1:window.lnDebug===!0||window.lnCore&&window.lnCore._debugSink?!0:typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug")||document.body.querySelector("[data-ln-debug]")!==null:!1}function L(e){if(typeof window>"u")return!1;if(window.lnDebug===!0)return!0;if(window.lnCore&&window.lnCore._debugIsContained)return e?window.lnCore._debugIsContained(e):window.lnCore._debugSink!==null;if(e&&e.closest){const t=e.closest("[data-ln-debug]");return!(!t||typeof document<"u"&&t===document.documentElement)}return typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug"):!1}if(typeof window<"u"&&(window.lnCore=window.lnCore||{},!window.lnCore._warnBound)){window.lnCore._warnBound=!0;const e=console.warn;console.warn=function(...t){if(typeof t[0]=="string"&&(t[0].startsWith("[ln-")||t[0].startsWith("[lnCore"))){let r=null;for(let i=1;i<t.length;i++)if(t[i]&&t[i].nodeType===1){r=t[i];break}if(!L(r))return}e.apply(console,t)}}function v(e,t,n){const r=n||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,r),e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:r}))}function D(e,t){if(!document.body){document.addEventListener("DOMContentLoaded",function(){D(e,t)}),console.warn("["+t+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}function S(...e){return e.filter(t=>t!=null&&t!=="").map((t,n)=>n===0?t.replace(/\/+$/,""):t.replace(/^\/+/,"").replace(/\/+$/,"")).filter(Boolean).join("/")}function T(e,t){return Object.assign({"Content-Type":"application/json",Accept:"application/json"},e,t?{Authorization:t}:null)}function K(e,t="ln-core"){try{return e?JSON.parse(e):{}}catch(n){return console.error(`[${t}] Invalid headers JSON:`,n),{}}}const N={};function G(e,t){N[e]=t}function Q(e){return N[e]||{ingress:t=>t,egress:t=>t}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=G,window.lnCore.getDataMapper=Q);function z(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,D(function(){new MutationObserver(function(){v(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const P={};function X(e,t){if(!e||typeof t!="object")return;const n=e.toLowerCase().split("-")[0];P[n]=t}function Y(e){if(!e)return null;const t=e.toLowerCase().split("-")[0];return P[t]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=X,window.lnCore.getLocaleFallback=Y,window.lnCore.ensureLocaleObserver=z);const x={};function Z(e,t){x[e]||(x[e]=document.querySelector('[data-ln-template="'+e+'"]'));const n=x[e];return n?n.content.cloneNode(!0):(console.warn("["+(t||"ln-core")+'] Template "'+e+'" not found'),null)}function M(e,t){if(!e||!t)return e;const n=e.querySelectorAll("[data-ln-field]");for(let c=0;c<n.length;c++){const a=n[c],d=a.getAttribute("data-ln-field");t[d]!=null&&(a.textContent=t[d])}const r=e.querySelectorAll("[data-ln-attr]");for(let c=0;c<r.length;c++){const a=r[c],d=a.getAttribute("data-ln-attr").split(",");for(let w=0;w<d.length;w++){const m=d[w].trim().split(":");if(m.length!==2)continue;const g=m[0].trim(),y=m[1].trim();t[y]!=null&&a.setAttribute(g,t[y])}}const i=e.querySelectorAll("[data-ln-show]");for(let c=0;c<i.length;c++){const a=i[c],d=a.getAttribute("data-ln-show");d in t&&a.classList.toggle("hidden",!t[d])}const s=e.querySelectorAll("[data-ln-class]");for(let c=0;c<s.length;c++){const a=s[c],d=a.getAttribute("data-ln-class").split(",");for(let w=0;w<d.length;w++){const m=d[w].trim().split(":");if(m.length!==2)continue;const g=m[0].trim(),y=m[1].trim();y in t&&a.classList.toggle(g,!!t[y])}}return e}function ee(e,t){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,t??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0})));const n=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let r=0;r<n.length;r++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",n[r],t??null),n[r].dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0}));return e}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(e){if(!(!e.target.matches||!e.target.matches("[data-ln-fillable]")))if(e.detail)M(e.target,e.detail);else{const t=e.target.querySelectorAll("[data-ln-field]");for(let n=0;n<t.length;n++)t[n].textContent=""}})));function H(e,t){if(!e||!t)return e;const n=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;n.nextNode();){const s=n.currentNode;s.textContent.indexOf("{{")!==-1&&(s.textContent=s.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(c,a){return t[a]!==void 0?t[a]:""}))}const r=function(s,c){return t[c]!==void 0?t[c]:""},i=Array.from(e.querySelectorAll("*"));e.nodeType===1&&i.push(e);for(let s=0;s<i.length;s++){const c=i[s],a=c.attributes;for(let d=0;d<a.length;d++){const w=a[d];w.value.indexOf("{{")!==-1&&c.setAttribute(w.name,w.value.replace(/\{\{\s*(\w+)\s*\}\}/g,r))}}return e}function te(e,t,n,r,i,s){const c={};for(let d=0;d<e.children.length;d++){const w=e.children[d],m=w.getAttribute("data-ln-render-key");m&&(c[m]=w)}const a=document.createDocumentFragment();for(let d=0;d<t.length;d++){const w=t[d],m=String(r(w));let g=c[m];if(g)i(g,w,d);else{const y=Z(n,s);if(!y||(H(y,w),g=y.firstElementChild,!g))continue;g.setAttribute("data-ln-render-key",m),i(g,w,d)}a.appendChild(g)}e.textContent="",e.appendChild(a)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=H,window.lnCore.fill=M,window.lnCore.lnFill=ee,window.lnCore.renderList=te);function E(e,t,n){const r=e.getAttribute(t);return r===null?n:r}function ne(e,t,n){const r=parseInt(e.getAttribute(t),10);return isNaN(r)?n:r}function re(e,t,n=!1){const r=e.getAttribute(t);if(r===null)return!!n;const i=r.trim().toLowerCase();return!(i==="false"||i==="0")}function oe(e,t){return(e.getAttribute(t)||"").split(",").map(n=>n.trim()).filter(Boolean)}const j=new Map;function ie(e,t){const n=(e?e.join("|"):"")+"::"+t;if(j.has(n))return j.get(n);const r=new Set(e||[]),i=function(s,c){const a=s.getAttribute(c);return a!==null&&r.has(a)?a:t};return j.set(n,i),i}function ce(e,t,n){const r=parseFloat(e.getAttribute(t));return isNaN(r)?n:r}function se(e,t,n){const r=e.getAttribute(t);if(!r)return n;try{return JSON.parse(r)}catch{return n}}function F(e,t,n,r,i){if(!e||t===null)return!0;const s=r||"ln-component",c=e.type;if(c==="trigger"||c==="marker"||c==="string"||c==="list"||!c||t===""&&e.fallback!==void 0)return!0;const a=d=>{i?console.warn(d,i):console.warn(d)};if(c==="boolean"){const d=t.trim().toLowerCase();return d!==""&&d!=="true"&&d!=="false"&&d!=="1"&&d!=="0"?(a(`[${s}] Invalid value "${t}" for boolean attribute "${n}". Allowed: "true", "false", or presence-only.`),!1):!0}if(c==="enum"){const d=e.values||[];return d.includes(t)?!0:(a(`[${s}] Invalid value "${t}" for attribute "${n}". Allowed: ${d.join(", ")}. Fallback: "${e.fallback}".`),!1)}if(c==="integer"){if(!/^-?\d+$/.test(t))return a(`[${s}] Invalid integer "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1;const d=parseInt(t,10);return e.min!==void 0&&d<e.min?(a(`[${s}] Value ${d} for attribute "${n}" is less than min (${e.min}).`),!1):e.max!==void 0&&d>e.max?(a(`[${s}] Value ${d} for attribute "${n}" is greater than max (${e.max}).`),!1):!0}if(c==="float")return isNaN(Number(t))?(a(`[${s}] Invalid float "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1):!0;if(c==="json")try{return JSON.parse(t),!0}catch(d){return a(`[${s}] Invalid JSON for attribute "${n}": ${d.message}. Fallback: ${e.fallback}.`),!1}return!0}function le(e,t,n){for(const r in n){const[i,s,c]=n[r];Object.defineProperty(e,r,{get:function(){return i(t,s,c)},enumerable:!0,configurable:!0})}return e}function ae(e){const t={};for(const n in e){const r=e[n];if(!r||!r.prop)continue;let i=r.read;if(!i&&r.type)switch(r.type){case"enum":i=ie(r.values,r.fallback);break;case"integer":i=ne;break;case"float":i=ce;break;case"boolean":i=re;break;case"list":i=oe;break;case"json":i=se;break;case"string":default:i=E;break}i||(i=E),t[r.prop]=[i,n,r.fallback]}return t}function de(e){const t={};for(const n in e){const r=e[n];r&&r.effect&&(t[n]=r.effect)}return Object.keys(t).length?t:null}function ue(e){if(e.onAttrChange&&!e.declared)return null;const t=new Set;if(e.effects)for(const n in e.effects)t.add(n);if(e.onAttrChange&&e.declared)for(const n of e.declared)t.add(n);return t}function I(e,t,n,r){if(e.nodeType!==1)return;const s=t.indexOf("[")!==-1||t.indexOf(".")!==-1||t.indexOf("#")!==-1?t:"["+t+"]",c=Array.from(e.querySelectorAll(s));e.matches&&e.matches(s)&&c.push(e);for(const a of c)if(!a[n]){window.lnCore._persistSink&&a.hasAttribute("data-ln-persist")&&window.lnCore._persistSink(a,t);try{a[n]=new r(a)}catch(d){console.error("["+n+"] init failed",a,d)}}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function fe(){return typeof window<"u"&&window.lnCore&&window.lnCore._bootHolds||0}function he(e){typeof window<"u"?(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[],window.lnCore._bootHolds>0?window.lnCore._bootQueue.push(e):setTimeout(e,0)):e()}function W(){window.lnCore=window.lnCore||{};const e=window.lnCore._attrRegistry=window.lnCore._attrRegistry||{byAttr:new Map,reactive:[],persist:[]};return e.byReactive=e.byReactive||new Map,e.reactiveWildcard=e.reactiveWildcard||[],e}function we(e){const t=W(),n=e.observed||[];for(let r=0;r<n.length;r++){const i=n[r];t.byAttr.has(i)||t.byAttr.set(i,[]),t.byAttr.get(i).push(e)}if(t.byDeclaredAttr=t.byDeclaredAttr||new Map,e.attributes)for(const r in e.attributes){t.byDeclaredAttr.has(r)||t.byDeclaredAttr.set(r,[]);const i=t.byDeclaredAttr.get(r);i.some(s=>s.componentTag===e.componentTag)||i.push({spec:e.attributes[r],componentTag:e.componentTag})}if(e.onAttrChange||e.effects){t.reactive.push(e);const r=ue(e);if(r===null)t.reactiveWildcard.push(e);else for(const i of r)t.byReactive.has(i)||t.byReactive.set(i,[]),t.byReactive.get(i).push(e)}e.persist&&t.persist.push(e)}function U(e,t,n,r){for(let i=0;i<e.length;i++){const s=e[i];if(!t[s.attribute])continue;const c=s.effects&&s.effects[n];c?c(t,n,r):s.onAttrChange&&(!s.declared||s.declared.has(n))&&s.onAttrChange(t,n,r)}}function be(e){const t=e.target,n=e.attributeName;if(e.oldValue===t.getAttribute(n))return;const r=W(),i=r.byAttr.get(n);if(B()&&r.byDeclaredAttr&&r.byDeclaredAttr.has(n)&&L(t)){const s=r.byDeclaredAttr.get(n),c=t.getAttribute(n);for(let a=0;a<s.length;a++)F(s[a].spec,c,n,s[a].componentTag,t)}if(window.lnCore._debugSink&&(n.indexOf("data-ln-")===0||i)&&window.lnCore._debugSink("attr",n,t,{oldValue:e.oldValue,newValue:t.getAttribute(n)}),n.indexOf("data-ln-")===0){const s=r.byReactive.get(n);s&&U(s,t,n,e.oldValue),r.reactiveWildcard.length&&U(r.reactiveWildcard,t,n,e.oldValue)}if(i)for(let s=0;s<i.length;s++){const c=i[s];if(c.handler){c.handler(t,n,e.oldValue);continue}c.onAttributeChange&&t[c.attribute]?c.onAttributeChange(t,n):(I(t,c.selector,c.attribute,c.ComponentFn),c.onInit&&c.onInit(t))}}function pe(){window.lnCore=window.lnCore||{},!window.lnCore._attrObserverBound&&(window.lnCore._attrObserverBound=!0,D(function(){new MutationObserver(function(t){for(let n=0;n<t.length;n++)try{be(t[n])}catch(r){console.error("[ln-core] mutation handler failed",t[n].target,r)}}).observe(document.body,{attributes:!0,subtree:!0,attributeOldValue:!0})},"ln-core"))}function J(){return window.lnCore=window.lnCore||{},window.lnCore._lifecycleRegistry=window.lnCore._lifecycleRegistry||[]}function ge(e){const t=J();if(t.length){if(e.target)for(let n=0;n<t.length;n++){const r=t[n];if(r.onSubtreeChange){const i=r.query,s=e.target.nodeType===1?e.target.matches(i)?e.target:e.target.closest(i):e.target.parentElement?e.target.parentElement.closest(i):null;s&&r.onSubtreeChange(s,e)}}for(let n=0;n<e.addedNodes.length;n++){const r=e.addedNodes[n];if(r.nodeType===1)for(let i=0;i<t.length;i++){const s=t[i];I(r,s.selector,s.attribute,s.ComponentFn),s.onInit&&s.onInit(r)}}for(let n=0;n<e.removedNodes.length;n++){const r=e.removedNodes[n];if(r.nodeType===1)for(let i=0;i<t.length;i++){const s=t[i],c=s.query,a=Array.from(r.querySelectorAll(c));r.matches&&r.matches(c)&&a.push(r);for(let d=0;d<a.length;d++){const w=a[d];if(!document.contains(w)){const m=w[s.attribute];if(m&&typeof m.destroy=="function")try{m.destroy()}catch(g){console.error("["+s.attribute+"] destroy failed",w,g)}delete w[s.attribute]}}}}}}function me(){window.lnCore=window.lnCore||{},!window.lnCore._lifecycleObserverBound&&(window.lnCore._lifecycleObserverBound=!0,D(function(){new MutationObserver(function(t){for(let n=0;n<t.length;n++){const r=t[n];if(r.type==="childList")try{ge(r)}catch(i){console.error("[ln-core] lifecycle handler failed",r.target,i)}}}).observe(document.body,{childList:!0,subtree:!0})},"ln-core"))}function Ce(e,t,n,r,i={}){const s=i.extraAttributes||[],c=i.onAttributeChange||null,a=i.onSubtreeChange||null,d=i.onInit||null,w=i.onAttrChange||null,m=i.effects||null,g=i.attributes||null,y=g?de(g):m,$=g?new Set(Object.keys(g)):null,o=i.persist||null;function u(h){const p=h||document.body;if(I(p,e,t,n),g&&B())for(const _ in g){const R=g[_],A=Array.from(p.querySelectorAll("["+_+"]"));p.matches&&p.matches("["+_+"]")&&A.push(p);for(let O=0;O<A.length;O++){const k=A[O];L(k)&&F(R,k.getAttribute(_),_,r,k)}}d&&d(p)}const l=[];if(e.indexOf("[")!==-1){const h=/\[([\w-]+)/g;let p;for(;(p=h.exec(e))!==null;)l.push(p[1])}else l.push(e);we({selector:e,attribute:t,componentTag:r,attributes:g,ComponentFn:n,onInit:d,observed:l.concat(s),onAttributeChange:c,onAttrChange:w,effects:y,declared:$,persist:o}),pe();const b=e.indexOf("[")!==-1||e.indexOf(".")!==-1||e.indexOf("#")!==-1?e:"["+e+"]";J().push({selector:e,attribute:t,ComponentFn:n,onInit:d,onSubtreeChange:a,query:b}),me(),window[t]=u;function C(){fe()>0?he(function(){u(document.body)}):u(document.body)}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",C):C(),u}function V(e){return(e||"").replace(/^#/,"")}function q(e){const t=e===void 0?location.hash:e,n={},r=V(t);if(!r)return n;const i=r.split("&");for(let s=0;s<i.length;s++){const c=i[s];if(!c)continue;const a=c.indexOf(":"),d=a>-1?c.slice(0,a):c,w=a>-1?c.slice(a+1):"";if(d)try{n[d]=decodeURIComponent(w)}catch{n[d]=w}}return n}function ye(e){if(!e)return null;const t=q();return e in t?t[e]:null}function _e(e,t){if(!e)return;const n=q();t==null?delete n[e]:n[e]=String(t);const i=Object.keys(n).map(function(s){const c=n[s];return c===""?s:s+":"+encodeURIComponent(c)}).join("&");V(location.hash)!==i&&(location.hash=i)}function ve(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function Ae(e,t){if(!e||!e.hasAttribute("data-ln-hash"))return null;const n=e.getAttribute("data-ln-hash");if(n&&n.trim()!=="")return n.trim();const r=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return r?t?r+"-"+t:r:t||null}function ke(e,t){return!t||t==="none"||e===null||e===void 0?null:String(e)+"."+t}function Se(e){return!e||typeof e!="string"?null:e.endsWith(".asc")?{fieldOrColumn:e.slice(0,-4),direction:"asc"}:e.endsWith(".desc")?{fieldOrColumn:e.slice(0,-5),direction:"desc"}:null}function Oe(e,t){return!e||!Array.isArray(t)||t.length===0?null:e+":"+t.map(encodeURIComponent).join(",")}function Te(e){if(!e||typeof e!="string")return null;const t=e.indexOf(":");if(t===-1)return null;const n=e.slice(0,t),r=e.slice(t+1),i=r?r.split(",").map(function(s){try{return decodeURIComponent(s)}catch{return s}}).filter(Boolean):[];return{key:n,values:i}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=q,window.lnCore.hashGet=ye,window.lnCore.hashSet=_e,window.lnCore.hashLinkClick=ve,window.lnCore.resolveHashNamespace=Ae,window.lnCore.hashSortEncode=ke,window.lnCore.hashSortDecode=Se,window.lnCore.hashFilterEncode=Oe,window.lnCore.hashFilterDecode=Te),(function(){const e="data-ln-couchdb-connector",t="lnCouchDbConnector",n="lnConnector";if(window[t]!==void 0)return;function r(o){const u=o[t];u&&u.refreshConfig()}const i={"data-ln-couchdb-connector":{type:"marker",description:"Mounts CouchDB/PouchDB connector bridging database and ln-ashlar data coordinators"},"data-ln-couchdb-url":{prop:"url",read:E,type:"string",fallback:"",effect:r,description:"CouchDB server base endpoint URL"},"data-ln-couchdb-db":{prop:"db",read:E,type:"string",fallback:"",effect:r,description:"Target CouchDB database name"},"data-ln-couchdb-auth":{prop:"auth",read:E,type:"string",fallback:"",effect:r,description:"Authentication credentials for CouchDB requests"},"data-ln-couchdb-headers":{effect:r,type:"json",fallback:null,description:"Custom HTTP headers in JSON or semicolon-separated format"}},s=ae(i);function c(o){const u=o&&o.content!==void 0?o.content:o,l=o&&o.message?o.message:null;return{content:u,message:l}}function a(o){return this.dom=o,le(this,o,s),o[t]=this,o[n]=this,this.refreshConfig(),this._handlers=null,$(this),this}a.prototype.refreshConfig=function(){const o=this.dom;this.credentials="same-origin";const u=o.getAttribute("data-ln-couchdb-headers")||"";this.headers=K(u,"ln-couchdb-connector"),this.auth&&console.warn("[ln-couchdb-connector] Security Warning: Sensitive authorization credentials detected in data-ln-couchdb-auth attribute. Storing basic authentication credentials in HTML DOM attributes is highly discouraged and vulnerable to XSS credential extraction. Please use HttpOnly session cookies or a Backend Proxy Gateway instead."),u.toLowerCase().includes("authorization")&&console.warn("[ln-couchdb-connector] Security Warning: Sensitive authorization credentials detected in data-ln-couchdb-headers attribute. Please use HttpOnly session cookies or a Backend Proxy Gateway instead."),v(o,"ln-couchdb-connector:config-changed",{url:this.url,db:this.db,auth:this.auth?"[REDACTED]":"",headers:this.headers})};function d(o,u,l){const f=Object.assign({},T(o.headers,o.auth),l||{});return u&&(f["Idempotency-Key"]=u),f}a.prototype.fetchDelta=function(o){const u=this,l=["include_docs=true","feed=normal"];o&&l.push("since="+encodeURIComponent(o));const f=S(u.url,u.db,"_changes")+"?"+l.join("&");return window.fetch(f,{method:"GET",headers:T(u.headers,u.auth),credentials:u.credentials}).then(b=>{if(!b.ok)throw new Error("HTTP "+b.status+": "+b.statusText);return b.json()}).then(b=>{const C=b.results||[];return{data:C.filter(h=>!h.deleted&&h.doc).map(h=>Object.assign({},h.doc,{id:h.doc._id})),deleted:C.filter(h=>h.deleted).map(h=>h.id),synced_at:b.last_seq||o||""}})};function w(o,u,l){const f=Object.assign({_id:u.id},u);return f._id||delete f._id,window.fetch(S(o.url,o.db),{method:"POST",headers:d(o,l),credentials:o.credentials,body:JSON.stringify(f)}).then(b=>{if(!b.ok)throw new Error("HTTP "+b.status+": "+b.statusText);return b.json()}).then(b=>{const C=c(b),h=C.content;return{record:Object.assign({},f,{id:h.id,_id:h.id,_rev:h.rev}),message:C.message}})}a.prototype.create=function(o,u){return w(this,o,u).then(l=>l.record)};function m(o,u,l,f){const b=Object.assign({id:String(u),_id:String(u)},l),C=b._rev||b.rev;return(C?Promise.resolve(C):window.fetch(S(o.url,o.db,null,u),{method:"GET",headers:T(o.headers,o.auth),credentials:o.credentials}).then(p=>{if(!p.ok)throw new Error("Could not retrieve document for revision mapping");return p.json().then(_=>_._rev)})).then(p=>{const _=Object.assign({},b,{_rev:p});delete _.rev;const R=d(o,f,{"If-Match":p});return window.fetch(S(o.url,o.db,null,u),{method:"PUT",headers:R,credentials:o.credentials,body:JSON.stringify(_)}).then(A=>{if(A.ok)return A.json().then(O=>{const k=c(O);return{record:Object.assign({},_,{_rev:k.content.rev}),message:k.message}});if(A.status===409)return A.json().then(O=>{const k=new Error("Conflict");throw k.status=409,k.data=O,k});throw new Error("HTTP "+A.status+": "+A.statusText)})})}a.prototype.update=function(o,u,l){return m(this,o,u,l).then(f=>f.record)};function g(o,u,l,f){return(l?Promise.resolve(l):window.fetch(S(o.url,o.db,null,u),{method:"GET",headers:T(o.headers,o.auth),credentials:o.credentials}).then(C=>{if(!C.ok)throw new Error("Could not retrieve document for revision delete");return C.json().then(h=>h._rev)})).then(C=>{const h=S(o.url,o.db,null,u)+"?rev="+encodeURIComponent(C);return window.fetch(h,{method:"DELETE",headers:d(o,f),credentials:o.credentials}).then(p=>{if(!p.ok)throw new Error("HTTP "+p.status+": "+p.statusText);return p.json()}).then(p=>{const _=c(p);return{response:_.content,message:_.message}})})}a.prototype.delete=function(o,u,l){return g(this,o,u,l).then(f=>f.response)};function y(o,u,l){return!u||u.length===0?Promise.resolve({response:{ok:!0,deletedCount:0},message:null}):window.fetch(S(o.url,o.db,"_all_docs"),{method:"POST",headers:T(o.headers,o.auth),credentials:o.credentials,body:JSON.stringify({keys:u})}).then(f=>{if(!f.ok)throw new Error("HTTP "+f.status+": "+f.statusText);return f.json()}).then(f=>{const C=(f.rows||[]).filter(h=>!h.error&&h.value&&h.value.rev).map(h=>({_id:h.id,_rev:h.value.rev,_deleted:!0}));return C.length===0?{response:{ok:!0,deletedCount:0},message:null}:window.fetch(S(o.url,o.db,"_bulk_docs"),{method:"POST",headers:d(o,l),credentials:o.credentials,body:JSON.stringify({docs:C})}).then(h=>{if(!h.ok)throw new Error("HTTP "+h.status+": "+h.statusText);return h.json()}).then(h=>{const p=c(h);return{response:{ok:!0,results:p.content,deletedCount:C.length},message:p.message}})})}a.prototype.bulkDelete=function(o,u){return y(this,o,u).then(l=>l.response)};function $(o){o._handlers={sync:function(u){const l=u.detail||{};o.fetchDelta(l.since).then(function(f){v(o.dom,"ln-couchdb-connector:fetched",{data:f,since:l.since,meta:l.meta||null})}).catch(function(f){v(o.dom,"ln-couchdb-connector:error",{action:"sync",error:f.message,status:f.status||0,since:l.since,meta:l.meta||null})})},create:function(u){const l=u.detail||{};w(o,l.data,l.idempotencyKey).then(function(f){v(o.dom,"ln-couchdb-connector:created",{record:f.record,tempId:l.tempId,message:f.message,meta:l.meta||null})}).catch(function(f){v(o.dom,"ln-couchdb-connector:error",{action:"create",error:f.message,status:f.status||0,tempId:l.tempId,meta:l.meta||null})})},update:function(u){const l=u.detail||{},f=Object.assign({},l.data);l.expected_version!==void 0&&(f._rev=l.expected_version),m(o,l.id,f,l.idempotencyKey).then(function(b){v(o.dom,"ln-couchdb-connector:updated",{record:b.record,id:l.id,message:b.message,meta:l.meta||null})}).catch(function(b){v(o.dom,"ln-couchdb-connector:error",{action:"update",error:b.message,status:b.status||0,id:l.id,data:b.status===409?b.data:null,conflictData:b.status===409?b.data:null,meta:l.meta||null})})},delete:function(u){const l=u.detail||{};g(o,l.id,l.rev,l.idempotencyKey).then(function(f){v(o.dom,"ln-couchdb-connector:deleted",{response:f.response,id:l.id,message:f.message,meta:l.meta||null})}).catch(function(f){v(o.dom,"ln-couchdb-connector:error",{action:"delete",error:f.message,status:f.status||0,id:l.id,meta:l.meta||null})})},bulkDelete:function(u){const l=u.detail||{};y(o,l.ids,l.idempotencyKey).then(function(f){v(o.dom,"ln-couchdb-connector:bulk-deleted",{response:f.response,ids:l.ids,message:f.message,meta:l.meta||null})}).catch(function(f){v(o.dom,"ln-couchdb-connector:error",{action:"bulk-delete",error:f.message,status:f.status||0,ids:l.ids,meta:l.meta||null})})}},o.dom.addEventListener("ln-couchdb-connector:request-sync",o._handlers.sync),o.dom.addEventListener("ln-couchdb-connector:request-create",o._handlers.create),o.dom.addEventListener("ln-couchdb-connector:request-update",o._handlers.update),o.dom.addEventListener("ln-couchdb-connector:request-delete",o._handlers.delete),o.dom.addEventListener("ln-couchdb-connector:request-bulk-delete",o._handlers.bulkDelete)}a.prototype.destroy=function(){if(!this.dom[t])return;const o=this;o._handlers&&(o.dom.removeEventListener("ln-couchdb-connector:request-sync",o._handlers.sync),o.dom.removeEventListener("ln-couchdb-connector:request-create",o._handlers.create),o.dom.removeEventListener("ln-couchdb-connector:request-update",o._handlers.update),o.dom.removeEventListener("ln-couchdb-connector:request-delete",o._handlers.delete),o.dom.removeEventListener("ln-couchdb-connector:request-bulk-delete",o._handlers.bulkDelete),o._handlers=null),delete this.dom[t],delete this.dom[n]},Ce(e,t,a,"ln-couchdb-connector",{attributes:i})})()})();
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "This file is partly generated. The $comment, component, generator, and each attribute's direction, sources, type, values, fallback, and description keys are owned by the generator and synchronized from JS source code. All other keys are preserved and safe to hand-author. Regenerate with `npm run sync:ln-schemas`.",
|
|
3
|
+
"component": "ln-couchdb-connector",
|
|
4
|
+
"generator": "scripts/sync-ln-schemas.mjs",
|
|
5
|
+
"attributes": {
|
|
6
|
+
"data-ln-couchdb-auth": {
|
|
7
|
+
"direction": null,
|
|
8
|
+
"sources": [
|
|
9
|
+
"src/ln-couchdb-connector.js"
|
|
10
|
+
],
|
|
11
|
+
"type": "string",
|
|
12
|
+
"fallback": "",
|
|
13
|
+
"description": "Authentication credentials for CouchDB requests"
|
|
14
|
+
},
|
|
15
|
+
"data-ln-couchdb-connector": {
|
|
16
|
+
"direction": null,
|
|
17
|
+
"sources": [
|
|
18
|
+
"src/ln-couchdb-connector.js"
|
|
19
|
+
],
|
|
20
|
+
"type": "marker",
|
|
21
|
+
"description": "Mounts CouchDB/PouchDB connector bridging database and ln-ashlar data coordinators"
|
|
22
|
+
},
|
|
23
|
+
"data-ln-couchdb-db": {
|
|
24
|
+
"direction": null,
|
|
25
|
+
"sources": [
|
|
26
|
+
"src/ln-couchdb-connector.js"
|
|
27
|
+
],
|
|
28
|
+
"type": "string",
|
|
29
|
+
"fallback": "",
|
|
30
|
+
"description": "Target CouchDB database name"
|
|
31
|
+
},
|
|
32
|
+
"data-ln-couchdb-headers": {
|
|
33
|
+
"direction": "author",
|
|
34
|
+
"sources": [
|
|
35
|
+
"src/ln-couchdb-connector.js"
|
|
36
|
+
],
|
|
37
|
+
"type": "json",
|
|
38
|
+
"description": "Custom HTTP headers in JSON or semicolon-separated format"
|
|
39
|
+
},
|
|
40
|
+
"data-ln-couchdb-url": {
|
|
41
|
+
"direction": null,
|
|
42
|
+
"sources": [
|
|
43
|
+
"src/ln-couchdb-connector.js"
|
|
44
|
+
],
|
|
45
|
+
"type": "string",
|
|
46
|
+
"fallback": "",
|
|
47
|
+
"description": "CouchDB server base endpoint URL"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|