@livenetworks/ashlar 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +189 -177
- package/js/COMPONENTS.md +55 -49
- package/js/index.js +22 -5
- package/js/ln-accordion/README.md +186 -137
- package/js/ln-accordion/ln-accordion.js +1 -1
- package/js/ln-ajax/README.md +73 -4
- package/js/ln-ajax/ln-ajax.js +1 -1
- package/js/ln-ajax/src/ln-ajax.js +13 -13
- package/js/ln-api-connector/README.md +261 -150
- package/js/ln-api-connector/ln-api-connector.js +1 -1
- package/js/ln-api-connector/src/ln-api-connector.js +368 -265
- package/js/ln-api-queue/README.md +219 -0
- package/js/ln-api-queue/ln-api-queue.js +1 -0
- package/js/ln-api-queue/src/ln-api-queue.js +320 -0
- package/js/ln-api-queue/src/queue-storage.js +455 -0
- package/js/ln-autoresize/README.md +47 -0
- package/js/ln-autoresize/ln-autoresize.js +1 -1
- package/js/ln-autosave/README.md +33 -1
- package/js/ln-autosave/ln-autosave.js +1 -1
- package/js/ln-autosave/src/ln-autosave.js +4 -4
- package/js/ln-circular-progress/README.md +27 -13
- package/js/ln-circular-progress/ln-circular-progress.js +1 -1
- package/js/ln-circular-progress/src/ln-circular-progress.js +18 -5
- package/js/ln-confirm/README.md +162 -86
- package/js/ln-confirm/_ln-confirm.scss +11 -0
- package/js/ln-confirm/ln-confirm.js +1 -1
- package/js/ln-confirm/src/ln-confirm.js +77 -41
- package/js/ln-core/README.md +896 -0
- package/js/ln-core/hash.js +92 -0
- package/js/ln-core/helpers.js +337 -8
- package/js/ln-core/index.js +4 -2
- package/js/ln-core/persist.js +29 -3
- package/js/ln-core/positioning.js +1 -35
- package/js/ln-core/window-cache.js +213 -0
- package/js/ln-couchdb-connector/README.md +177 -156
- package/js/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
- package/js/ln-couchdb-connector/src/ln-couchdb-connector.js +398 -348
- package/js/ln-data-coordinator/README.md +536 -165
- package/js/ln-data-coordinator/ln-data-coordinator.js +1 -1
- package/js/ln-data-coordinator/src/data-read-policy.js +18 -0
- package/js/ln-data-coordinator/src/ln-data-coordinator.js +1042 -249
- package/js/ln-data-coordinator/src/mutation-receipts.js +46 -0
- package/js/ln-data-store/README.md +241 -94
- package/js/ln-data-store/ln-data-store.js +1 -1
- package/js/ln-data-store/src/ln-data-store.js +694 -699
- package/js/ln-date/README.md +39 -1
- package/js/ln-date/ln-date-dev.scss +14 -0
- package/js/ln-date/ln-date.js +1 -1
- package/js/ln-date/src/ln-date.js +236 -178
- package/js/ln-debug/README.md +58 -0
- package/js/ln-debug/ln-debug.js +1 -0
- package/js/ln-debug/src/ln-debug.js +19 -0
- package/js/ln-dropdown/README.md +31 -8
- package/js/ln-dropdown/ln-dropdown.js +1 -1
- package/js/ln-dropdown/src/ln-dropdown.js +30 -13
- package/js/ln-editor/README.md +274 -0
- package/js/ln-editor/ln-editor.js +1 -0
- package/js/ln-editor/ln-editor.scss +43 -0
- package/js/ln-editor/src/ln-editor.js +619 -0
- package/js/ln-external-links/README.md +44 -5
- package/js/ln-external-links/ln-external-links.js +1 -1
- package/js/ln-fill/README.md +199 -0
- package/js/ln-fill/ln-fill.js +1 -0
- package/js/ln-fill/src/ln-fill.js +87 -0
- package/js/ln-filter/README.md +189 -99
- package/js/ln-filter/ln-filter-dev.scss +8 -0
- package/js/ln-filter/ln-filter.js +1 -1
- package/js/ln-filter/src/ln-filter.js +22 -7
- package/js/ln-form/README.md +212 -49
- package/js/ln-form/ln-form.js +1 -1
- package/js/ln-form/src/ln-form.js +99 -199
- package/js/ln-http/README.md +125 -89
- package/js/ln-http/ln-http.js +1 -1
- package/js/ln-http/src/ln-http.js +32 -13
- package/js/ln-icon/README.md +130 -0
- package/js/ln-icon/ln-icon.js +1 -0
- package/js/{ln-icons/src/ln-icons.js → ln-icon/src/ln-icon.js} +20 -15
- package/js/ln-link/README.md +47 -9
- package/js/ln-link/ln-link.js +1 -1
- package/js/ln-link/src/ln-link.js +22 -6
- package/js/ln-list/README.md +129 -0
- package/js/ln-list/ln-list.js +1 -0
- package/js/ln-list/ln-list.scss +28 -0
- package/js/ln-list/src/ln-list.js +1216 -0
- package/js/ln-modal/README.md +185 -154
- package/js/ln-modal/ln-modal-dev.scss +13 -0
- package/js/ln-modal/ln-modal.js +1 -1
- package/js/ln-modal/ln-modal.scss +28 -4
- package/js/ln-modal/src/ln-modal.js +137 -201
- package/js/ln-modal-coordinator/README.md +99 -0
- package/js/ln-modal-coordinator/ln-modal-coordinator-dev.scss +8 -0
- package/js/ln-modal-coordinator/ln-modal-coordinator.js +1 -0
- package/js/ln-modal-coordinator/src/ln-modal-coordinator.js +345 -0
- package/js/ln-nav/README.md +46 -3
- package/js/ln-nav/ln-nav.js +1 -1
- package/js/ln-nav/src/ln-nav.js +92 -127
- package/js/ln-number/README.md +28 -1
- package/js/ln-number/ln-number-dev.scss +13 -0
- package/js/ln-number/ln-number.js +1 -1
- package/js/ln-number/src/ln-number.js +443 -350
- package/js/ln-options/README.md +66 -0
- package/js/ln-options/ln-options.js +1 -0
- package/js/ln-options/src/ln-options.js +74 -0
- package/js/ln-popover/README.md +40 -5
- package/js/ln-popover/ln-popover.js +1 -1
- package/js/ln-popover/src/ln-popover.js +38 -11
- package/js/ln-progress/README.md +413 -442
- package/js/ln-progress/ln-progress.js +1 -1
- package/js/ln-progress/src/ln-progress.js +98 -150
- package/js/ln-router/README.md +432 -0
- package/js/ln-router/ln-router.js +1 -0
- package/js/ln-router/src/ln-router.js +539 -0
- package/js/ln-search/README.md +158 -83
- package/js/ln-search/ln-search-dev.scss +8 -0
- package/js/ln-search/ln-search.js +1 -1
- package/js/ln-search/src/ln-search.js +12 -9
- package/js/ln-slug/README.md +110 -0
- package/js/ln-slug/ln-slug.js +1 -0
- package/js/ln-slug/src/ln-slug.js +74 -0
- package/js/ln-sort/README.md +170 -0
- package/js/ln-sort/ln-sort-dev.scss +8 -0
- package/js/ln-sort/ln-sort.js +1 -0
- package/js/ln-sort/src/ln-sort.js +178 -0
- package/js/ln-sortable/README.md +133 -95
- package/js/ln-sortable/ln-sortable.js +1 -1
- package/js/ln-stat/README.md +55 -0
- package/js/ln-stat/ln-stat.js +1 -0
- package/js/ln-stat/src/ln-stat.js +55 -0
- package/js/ln-table/README.md +285 -101
- package/js/ln-table/ln-table-dev.scss +17 -0
- package/js/ln-table/ln-table.js +1 -1
- package/js/ln-table/ln-table.scss +1 -1
- package/js/ln-table/src/ln-table.js +1493 -473
- package/js/ln-table-coordinator/README.md +73 -0
- package/js/ln-table-coordinator/ln-table-coordinator.js +1 -0
- package/js/ln-table-coordinator/src/ln-table-coordinator.js +160 -0
- package/js/ln-tabs/README.md +221 -137
- package/js/ln-tabs/ln-tabs-dev.scss +18 -0
- package/js/ln-tabs/ln-tabs.js +1 -1
- package/js/ln-tabs/src/ln-tabs.js +41 -24
- package/js/ln-time/README.md +14 -0
- package/js/ln-time/ln-time.js +1 -1
- package/js/ln-time/src/ln-time.js +223 -192
- package/js/ln-toast/README.md +178 -122
- package/js/ln-toast/ln-toast.js +1 -15
- package/js/ln-toast/src/ln-toast.js +232 -210
- package/js/ln-toast/template.html +16 -12
- package/js/ln-toggle/README.md +61 -2
- package/js/ln-toggle/ln-toggle-dev.scss +13 -0
- package/js/ln-toggle/ln-toggle.js +1 -1
- package/js/ln-toggle/src/ln-toggle.js +56 -43
- package/js/ln-tooltip/README.md +95 -58
- package/js/ln-tooltip/ln-tooltip-dev.scss +9 -0
- package/js/ln-tooltip/ln-tooltip.js +1 -1
- package/js/ln-tooltip/src/ln-tooltip.js +45 -6
- package/js/ln-translations/README.md +118 -96
- package/js/ln-translations/ln-translations.js +1 -1
- package/js/ln-translations/src/ln-translations.js +10 -5
- package/js/ln-upload/README.md +85 -10
- package/js/ln-upload/ln-upload.js +1 -1
- package/js/ln-upload/src/ln-upload.js +26 -10
- package/js/ln-validate/README.md +72 -0
- package/js/ln-validate/ln-validate-dev.scss +15 -0
- package/js/ln-validate/ln-validate.js +1 -1
- package/js/ln-validate/src/ln-validate.js +64 -0
- package/package.json +61 -55
- package/scss/base/_global.scss +2 -2
- package/scss/base/_typography.scss +1 -2
- package/scss/components/_date.scss +1 -0
- package/scss/components/_dropdown.scss +0 -5
- package/scss/components/_editor.scss +5 -0
- package/scss/components/_filter.scss +26 -0
- package/scss/components/_form.scss +7 -0
- package/scss/components/_ln-table.scss +14 -5
- package/scss/components/_sort.scss +10 -0
- package/scss/components/_table.scss +68 -1
- package/scss/components/_toast.scss +68 -41
- package/scss/components/_toggle.scss +16 -0
- package/scss/config/_density.scss +205 -117
- package/scss/config/_icons.scss +10 -9
- package/scss/config/_tokens.scss +69 -47
- package/scss/config/mixins/_accordion.scss +2 -7
- package/scss/config/mixins/_alert.scss +4 -4
- package/scss/config/mixins/_breadcrumbs.scss +2 -2
- package/scss/config/mixins/_btn.scss +1 -1
- package/scss/config/mixins/_card.scss +89 -14
- package/scss/config/mixins/_collapsible.scss +3 -0
- package/scss/config/mixins/_colors.scss +1 -1
- package/scss/config/mixins/_diagnostics.scss +48 -0
- package/scss/config/mixins/_display.scss +1 -0
- package/scss/config/mixins/_dropdown.scss +3 -5
- package/scss/config/mixins/_editor.scss +124 -0
- package/scss/config/mixins/_empty-state.scss +7 -0
- package/scss/config/mixins/_filter.scss +47 -0
- package/scss/config/mixins/_footer.scss +1 -2
- package/scss/config/mixins/_form.scss +207 -21
- package/scss/config/mixins/_index.scss +4 -1
- package/scss/config/mixins/_ln-table.scss +51 -93
- package/scss/config/mixins/_modal.scss +149 -66
- package/scss/config/mixins/_nav.scss +3 -4
- package/scss/config/mixins/_popover.scss +39 -0
- package/scss/config/mixins/_sidebar.scss +1 -1
- package/scss/config/mixins/_sort.scss +42 -0
- package/scss/config/mixins/_table.scss +232 -38
- package/scss/config/mixins/_toast.scss +179 -152
- package/scss/config/mixins/_tooltip.scss +17 -7
- package/scss/config/mixins/_typography.scss +4 -2
- package/scss/ln-ashlar-dev.scss +39 -0
- package/scss/ln-ashlar.scss +8 -2
- package/js/ln-data-table/README.md +0 -110
- package/js/ln-data-table/ln-data-table.js +0 -1
- package/js/ln-data-table/ln-data-table.scss +0 -10
- package/js/ln-data-table/src/ln-data-table.js +0 -1103
- package/js/ln-icons/README.md +0 -88
- package/js/ln-icons/ln-icons.js +0 -1
- package/js/ln-table/ln-table-sort.js +0 -1
- package/js/ln-table/src/ln-table-sort.js +0 -168
- package/scss/components/_data-table.scss +0 -83
- package/scss/config/mixins/_data-table.scss +0 -346
package/js/ln-icons/README.md
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
# ln-icons
|
|
2
|
-
|
|
3
|
-
A zero-dependency, local-first **On-Demand SVG Sprite Generator** that dynamically monitors, fetches, and compiles SVG icons at runtime.
|
|
4
|
-
|
|
5
|
-
Instead of bundling thousands of heavy vector paths or requiring complex manual build steps, it intercepts standard DOM `<use>` tags, fetches vector definitions from a remote CDN, caches them in `localStorage`, and injects them into a single unified hidden SVG sprite sheet.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 🧭 Philosophy & Architecture
|
|
10
|
-
|
|
11
|
-
1. **Declarative On-Demand Rendering:** Icons are declared directly in HTML. The component monitors the DOM via `MutationObserver` for `<use>` references with `#ln-` and `#lnc-` prefixes. It only fetches and compiles icons that are actively present on the page.
|
|
12
|
-
2. **Dual-Prefix Routing:**
|
|
13
|
-
- **`#ln-{name}`**: Automatically routes to the [Tabler Icons](https://tabler.io/icons) library fetched from a public CDN. No configuration required.
|
|
14
|
-
- **`#lnc-{name}`**: Routes to a custom corporate CDN defined via global window settings.
|
|
15
|
-
3. **Local Caching Layer:** Fetched SVG path structures are instantly cached in `localStorage` under `lni:{id}`. Subsequent visits render icons instantly with zero network roundtrips.
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## 📦 Minimal Blueprint
|
|
20
|
-
|
|
21
|
-
### Native Tabler Icon
|
|
22
|
-
```html
|
|
23
|
-
<svg class="ln-icon" aria-hidden="true">
|
|
24
|
-
<use href="#ln-home"></use>
|
|
25
|
-
</svg>
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### Custom Asset Icon
|
|
29
|
-
Define your custom CDN endpoint before importing the library:
|
|
30
|
-
```html
|
|
31
|
-
<script>
|
|
32
|
-
window.LN_ICONS_CUSTOM_CDN = "https://cdn.mycompany.com/assets/icons";
|
|
33
|
-
</script>
|
|
34
|
-
<script src="dist/ln-ashlar.iife.js" defer></script>
|
|
35
|
-
|
|
36
|
-
<!-- Renders icon from your custom CDN -->
|
|
37
|
-
<svg class="ln-icon" aria-hidden="true">
|
|
38
|
-
<use href="#lnc-corporate-logo"></use>
|
|
39
|
-
</svg>
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## 🛠️ Declarative API Contract
|
|
45
|
-
|
|
46
|
-
### CSS Utility Classes
|
|
47
|
-
|
|
48
|
-
Configure icon sizes and alignments using standard CSS classes:
|
|
49
|
-
|
|
50
|
-
| Class | Size | Description |
|
|
51
|
-
| :--- | :--- | :--- |
|
|
52
|
-
| `ln-icon` | `1.25rem` | Base styles, sets `fill: none`, `stroke: currentColor`, inherits color. |
|
|
53
|
-
| `ln-icon--sm` | `1rem` | Small icon, designed for inline text badges or buttons. |
|
|
54
|
-
| `ln-icon--lg` | `1.5rem` | Large icon, designed for toolbar buttons. |
|
|
55
|
-
| `ln-icon--xl` | `4rem` | Extra-large icon, designed for empty state illustrations. |
|
|
56
|
-
| `ln-chevron` | — | Automatically rotates `90deg` when an ancestor `.is-active` class is toggled. |
|
|
57
|
-
|
|
58
|
-
### Global Configuration (`window`)
|
|
59
|
-
|
|
60
|
-
Configure these properties before script initialization:
|
|
61
|
-
|
|
62
|
-
| Variable | Default | Description |
|
|
63
|
-
| :--- | :--- | :--- |
|
|
64
|
-
| `LN_ICONS_CDN` | `https://cdn.jsdelivr.net/npm/@tabler/icons@3.31.0/icons/outline` | Base CDN URL for Tabler Icons. |
|
|
65
|
-
| `LN_ICONS_CUSTOM_CDN` | `null` | Base CDN URL for custom `#lnc-` prefixed SVG resources. |
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
## ⚡ Dynamic Interaction Flow
|
|
70
|
-
|
|
71
|
-
### Automated Mutation Observability
|
|
72
|
-
The loader observes the DOM continuously. When new content is injected (e.g. by `ln-ajax` or `ln-store`), any new icon `<use>` tag is intercepted, resolved, and rendered.
|
|
73
|
-
|
|
74
|
-
### Dynamic Attribute Swaps
|
|
75
|
-
Modifying the `href` attribute of a `<use>` element dynamically via JavaScript triggers automatic resolution of the new target icon:
|
|
76
|
-
```javascript
|
|
77
|
-
const useElement = document.querySelector('use');
|
|
78
|
-
// Dynamically fetches and switches the icon to a checkmark
|
|
79
|
-
useElement.setAttribute('href', '#ln-check');
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## ⚠️ Common Pitfalls
|
|
85
|
-
|
|
86
|
-
- **Forgetting `ln-icon` Class:** Standard SVGs default to `100%` width/height. Failing to include the `ln-icon` class will cause the icon to blow up to full viewport size.
|
|
87
|
-
- **Incorrect Prefix Configuration:** Forgetting to define `window.LN_ICONS_CUSTOM_CDN` when using `#lnc-` will cause the loader to fail silently with undefined endpoint errors.
|
|
88
|
-
- **Omitting `aria-hidden="true"`:** Screen readers attempt to read SVG nodes. Always decorate decorative icons with `aria-hidden="true"`, or include an `aria-label` on their parent button.
|
package/js/ln-icons/ln-icons.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(){"use strict";(function(){const h="ln-icons-sprite",a="#ln-",o="#lnc-",d=new Set,l=new Set;let c=null;const C=(window.LN_ICONS_CDN||"https://cdn.jsdelivr.net/npm/@tabler/icons@3.31.0/icons/outline").replace(/\/$/,""),g=(window.LN_ICONS_CUSTOM_CDN||"").replace(/\/$/,""),u="lni:",m="lni:v",S="1";function v(){try{if(localStorage.getItem(m)!==S){for(let t=localStorage.length-1;t>=0;t--){const n=localStorage.key(t);n&&n.indexOf(u)===0&&localStorage.removeItem(n)}localStorage.setItem(m,S)}}catch{}}v();function N(){return c||(c=document.getElementById(h),c||(c=document.createElementNS("http://www.w3.org/2000/svg","svg"),c.id=h,c.setAttribute("hidden",""),c.setAttribute("aria-hidden","true"),c.appendChild(document.createElementNS("http://www.w3.org/2000/svg","defs")),document.body.insertBefore(c,document.body.firstChild))),c}function A(t){return t.indexOf(o)===0?g+"/"+t.slice(o.length)+".svg":C+"/"+t.slice(a.length)+".svg"}function w(t,n){const e=n.match(/viewBox="([^"]+)"/),i=e?e[1]:"0 0 24 24",s=n.match(/<svg[^>]*>([\s\S]*?)<\/svg>/i),I=s?s[1].trim():"",y=n.match(/<svg([^>]*)>/i),O=y?y[1]:"",r=document.createElementNS("http://www.w3.org/2000/svg","symbol");r.id=t,r.setAttribute("viewBox",i),["fill","stroke","stroke-width","stroke-linecap","stroke-linejoin"].forEach(function(_){const b=O.match(new RegExp(_+'="([^"]*)"'));b&&r.setAttribute(_,b[1])}),r.innerHTML=I,N().querySelector("defs").appendChild(r)}function f(t){if(d.has(t)||l.has(t)||t.indexOf(o)===0&&!g)return;const n=t.slice(1);try{const e=localStorage.getItem(u+n);if(e){w(n,e),d.add(t);return}}catch{}l.add(t),fetch(A(t)).then(function(e){if(!e.ok)throw new Error(e.status);return e.text()}).then(function(e){w(n,e),d.add(t),l.delete(t);try{localStorage.setItem(u+n,e)}catch{}}).catch(function(){l.delete(t)})}function E(t){const n='use[href^="'+a+'"], use[href^="'+o+'"]',e=t.querySelectorAll?t.querySelectorAll(n):[];if(t.matches&&t.matches(n)){const i=t.getAttribute("href");i&&f(i)}Array.prototype.forEach.call(e,function(i){const s=i.getAttribute("href");s&&f(s)})}function p(){E(document),new MutationObserver(function(t){t.forEach(function(n){if(n.type==="childList")n.addedNodes.forEach(function(e){e.nodeType===1&&E(e)});else if(n.type==="attributes"&&n.attributeName==="href"){const e=n.target.getAttribute("href");e&&(e.indexOf(a)===0||e.indexOf(o)===0)&&f(e)}})}).observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["href"]})}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",p):p()})()})();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(){"use strict";function _(t,o,l){t.dispatchEvent(new CustomEvent(o,{bubbles:!0,detail:l||{}}))}function d(t,o){if(!document.body){document.addEventListener("DOMContentLoaded",function(){d(t,o)}),console.warn("["+o+'] Script loaded before <body> — add "defer" to your <script> tag');return}t()}const f={};function g(t,o){f[t]=o}function w(t){return f[t]||{ingress:o=>o,egress:o=>o}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=g,window.lnCore.getDataMapper=w);const E="ln:";function S(){return location.pathname.replace(/\/+$/,"").toLowerCase()||"/"}function p(t,o){const l=o.getAttribute("data-ln-persist"),c=l!==null&&l!==""?l:o.id;return c?E+t+":"+S()+":"+c:(console.warn('[ln-persist] Element requires id or data-ln-persist="key"',o),null)}function v(t,o){const l=p(t,o);if(!l)return null;try{const c=localStorage.getItem(l);return c!==null?JSON.parse(c):null}catch{return null}}function b(t,o,l){const c=p(t,o);if(c)try{localStorage.setItem(c,JSON.stringify(l))}catch{}}(function(){const t="lnTableSort",o="data-ln-sort",l="data-ln-sort-active";if(window[t]!==void 0)return;function c(i){a(i)}function a(i){const r=Array.from(i.querySelectorAll("table"));i.tagName==="TABLE"&&r.push(i),r.forEach(function(e){if(e[t])return;const s=Array.from(e.querySelectorAll("th["+o+"]"));s.length&&(e[t]=new u(e,s))})}function h(i,r){i.querySelectorAll("[data-ln-sort-icon]").forEach(function(s){const n=s.getAttribute("data-ln-sort-icon");r==null?s.classList.toggle("hidden",n!==null&&n!==""):s.classList.toggle("hidden",n!==r)})}function u(i,r){this.table=i,this.ths=r,this._col=-1,this._dir=null;const e=this;r.forEach(function(n,m){n[t+"Bound"]||(n[t+"Bound"]=!0,n._lnSortClick=function(A){const y=A.target.closest("button, a, input, select, textarea, [data-ln-dropdown]");y&&y!==n||e._handleClick(m,n)},n.addEventListener("click",n._lnSortClick))});const s=i.closest("[data-ln-table][data-ln-persist]");if(s){const n=v("table-sort",s);n&&n.dir&&n.col>=0&&n.col<r.length&&(this._handleClick(n.col,r[n.col]),n.dir==="desc"&&this._handleClick(n.col,r[n.col]))}return this}u.prototype._handleClick=function(i,r){let e;this._col!==i?e="asc":this._dir==="asc"?e="desc":this._dir==="desc"?e=null:e="asc",this.ths.forEach(function(n){n.removeAttribute(l),h(n,null)}),e===null?(this._col=-1,this._dir=null):(this._col=i,this._dir=e,r.setAttribute(l,e),h(r,e)),_(this.table,"ln-table:sort",{column:i,sortType:r.getAttribute(o),direction:e});const s=this.table.closest("[data-ln-table][data-ln-persist]");s&&(e===null?b("table-sort",s,null):b("table-sort",s,{col:i,dir:e}))},u.prototype.destroy=function(){this.table[t]&&(this.ths.forEach(function(i){i._lnSortClick&&(i.removeEventListener("click",i._lnSortClick),delete i._lnSortClick),delete i[t+"Bound"]}),delete this.table[t])};function C(){d(function(){new MutationObserver(function(r){r.forEach(function(e){e.type==="childList"?e.addedNodes.forEach(function(s){s.nodeType===1&&a(s)}):e.type==="attributes"&&a(e.target)})}).observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[o]})},"ln-table-sort")}window[t]=c,C(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",function(){c(document.body)}):c(document.body)})()})();
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { guardBody, dispatch } from '../../ln-core';
|
|
2
|
-
import { persistGet, persistSet } from '../../ln-core';
|
|
3
|
-
|
|
4
|
-
(function () {
|
|
5
|
-
const DOM_ATTRIBUTE = 'lnTableSort';
|
|
6
|
-
const SORT_ATTR = 'data-ln-sort';
|
|
7
|
-
const SORT_ACTIVE_ATTR = 'data-ln-sort-active';
|
|
8
|
-
|
|
9
|
-
if (window[DOM_ATTRIBUTE] !== undefined) return;
|
|
10
|
-
|
|
11
|
-
// ─── Constructor ───────────────────────────────────────────
|
|
12
|
-
// Auto-initializes any <table> that contains th[data-ln-sort] headers.
|
|
13
|
-
|
|
14
|
-
function constructor(domRoot) {
|
|
15
|
-
findElements(domRoot);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Local findElements — intentional divergence from ln-core helper: tag selector ('table') + two-arg constructor (table, ths).
|
|
19
|
-
function findElements(root) {
|
|
20
|
-
const tables = Array.from(root.querySelectorAll('table'));
|
|
21
|
-
if (root.tagName === 'TABLE') tables.push(root);
|
|
22
|
-
|
|
23
|
-
tables.forEach(function (table) {
|
|
24
|
-
if (table[DOM_ATTRIBUTE]) return;
|
|
25
|
-
const ths = Array.from(table.querySelectorAll('th[' + SORT_ATTR + ']'));
|
|
26
|
-
if (ths.length) table[DOM_ATTRIBUTE] = new _component(table, ths);
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// ─── Component ─────────────────────────────────────────────
|
|
31
|
-
|
|
32
|
-
function _setSortIcon(th, dir) {
|
|
33
|
-
const icons = th.querySelectorAll('[data-ln-sort-icon]');
|
|
34
|
-
icons.forEach(function (icon) {
|
|
35
|
-
const val = icon.getAttribute('data-ln-sort-icon');
|
|
36
|
-
if (dir === null || dir === undefined) {
|
|
37
|
-
// Neutral: show the no-value icon, hide asc/desc
|
|
38
|
-
icon.classList.toggle('hidden', val !== null && val !== '');
|
|
39
|
-
} else {
|
|
40
|
-
// Show matching direction, hide others
|
|
41
|
-
icon.classList.toggle('hidden', val !== dir);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function _component(table, ths) {
|
|
47
|
-
this.table = table;
|
|
48
|
-
this.ths = ths;
|
|
49
|
-
this._col = -1;
|
|
50
|
-
this._dir = null;
|
|
51
|
-
const self = this;
|
|
52
|
-
|
|
53
|
-
ths.forEach(function (th, index) {
|
|
54
|
-
if (th[DOM_ATTRIBUTE + 'Bound']) return;
|
|
55
|
-
th[DOM_ATTRIBUTE + 'Bound'] = true;
|
|
56
|
-
|
|
57
|
-
th._lnSortClick = function (e) {
|
|
58
|
-
// Don't sort when user clicks an interactive child (filter button, etc.)
|
|
59
|
-
const interactive = e.target.closest('button, a, input, select, textarea, [data-ln-dropdown]');
|
|
60
|
-
if (interactive && interactive !== th) return;
|
|
61
|
-
self._handleClick(index, th);
|
|
62
|
-
};
|
|
63
|
-
th.addEventListener('click', th._lnSortClick);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// ─── Restore persisted sort ───────────────────────────────
|
|
67
|
-
const persistRoot = table.closest('[data-ln-table][data-ln-persist]');
|
|
68
|
-
if (persistRoot) {
|
|
69
|
-
const saved = persistGet('table-sort', persistRoot);
|
|
70
|
-
if (saved && saved.dir && saved.col >= 0 && saved.col < ths.length) {
|
|
71
|
-
// Programmatically trigger the saved sort
|
|
72
|
-
this._handleClick(saved.col, ths[saved.col]);
|
|
73
|
-
if (saved.dir === 'desc') {
|
|
74
|
-
this._handleClick(saved.col, ths[saved.col]);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return this;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
_component.prototype._handleClick = function (colIndex, th) {
|
|
83
|
-
let newDir;
|
|
84
|
-
|
|
85
|
-
if (this._col !== colIndex) {
|
|
86
|
-
newDir = 'asc';
|
|
87
|
-
} else if (this._dir === 'asc') {
|
|
88
|
-
newDir = 'desc';
|
|
89
|
-
} else if (this._dir === 'desc') {
|
|
90
|
-
newDir = null;
|
|
91
|
-
} else {
|
|
92
|
-
newDir = 'asc';
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
this.ths.forEach(function (t) {
|
|
96
|
-
t.removeAttribute(SORT_ACTIVE_ATTR);
|
|
97
|
-
_setSortIcon(t, null);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
if (newDir === null) {
|
|
101
|
-
this._col = -1;
|
|
102
|
-
this._dir = null;
|
|
103
|
-
} else {
|
|
104
|
-
this._col = colIndex;
|
|
105
|
-
this._dir = newDir;
|
|
106
|
-
th.setAttribute(SORT_ACTIVE_ATTR, newDir);
|
|
107
|
-
_setSortIcon(th, newDir);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
dispatch(this.table, 'ln-table:sort', {
|
|
111
|
-
column: colIndex,
|
|
112
|
-
sortType: th.getAttribute(SORT_ATTR),
|
|
113
|
-
direction: newDir
|
|
114
|
-
});
|
|
115
|
-
const persistRoot = this.table.closest('[data-ln-table][data-ln-persist]');
|
|
116
|
-
if (persistRoot) {
|
|
117
|
-
if (newDir === null) {
|
|
118
|
-
persistSet('table-sort', persistRoot, null);
|
|
119
|
-
} else {
|
|
120
|
-
persistSet('table-sort', persistRoot, { col: colIndex, dir: newDir });
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
_component.prototype.destroy = function () {
|
|
126
|
-
if (!this.table[DOM_ATTRIBUTE]) return;
|
|
127
|
-
this.ths.forEach(function (th) {
|
|
128
|
-
if (th._lnSortClick) {
|
|
129
|
-
th.removeEventListener('click', th._lnSortClick);
|
|
130
|
-
delete th._lnSortClick;
|
|
131
|
-
}
|
|
132
|
-
delete th[DOM_ATTRIBUTE + 'Bound'];
|
|
133
|
-
});
|
|
134
|
-
delete this.table[DOM_ATTRIBUTE];
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
// ─── DOM Observer ──────────────────────────────────────────
|
|
138
|
-
|
|
139
|
-
function _domObserver() {
|
|
140
|
-
guardBody(function () {
|
|
141
|
-
const observer = new MutationObserver(function (mutations) {
|
|
142
|
-
mutations.forEach(function (mutation) {
|
|
143
|
-
if (mutation.type === 'childList') {
|
|
144
|
-
mutation.addedNodes.forEach(function (node) {
|
|
145
|
-
if (node.nodeType === 1) findElements(node);
|
|
146
|
-
});
|
|
147
|
-
} else if (mutation.type === 'attributes') {
|
|
148
|
-
findElements(mutation.target);
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [SORT_ATTR] });
|
|
153
|
-
}, 'ln-table-sort');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// ─── Init ──────────────────────────────────────────────────
|
|
157
|
-
|
|
158
|
-
window[DOM_ATTRIBUTE] = constructor;
|
|
159
|
-
_domObserver();
|
|
160
|
-
|
|
161
|
-
if (document.readyState === 'loading') {
|
|
162
|
-
document.addEventListener('DOMContentLoaded', function () {
|
|
163
|
-
constructor(document.body);
|
|
164
|
-
});
|
|
165
|
-
} else {
|
|
166
|
-
constructor(document.body);
|
|
167
|
-
}
|
|
168
|
-
})();
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
@use '../config/mixins' as *;
|
|
2
|
-
|
|
3
|
-
[data-ln-data-table] {
|
|
4
|
-
@include data-table;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
// ─── Sort indicators ──────────────────────────────────────
|
|
8
|
-
|
|
9
|
-
[data-ln-col-sort] {
|
|
10
|
-
@include data-table-sort-button;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
th:hover [data-ln-col-sort] {
|
|
14
|
-
opacity: 0.7;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.ln-sort-asc [data-ln-col-sort],
|
|
18
|
-
.ln-sort-desc [data-ln-col-sort] {
|
|
19
|
-
@include data-table-sort-active;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Active-state icon swap — hide the neutral dual-arrow, show the
|
|
23
|
-
// matching directional icon. Mixin defaults all three to "none shown,
|
|
24
|
-
// asc/desc hidden"; we override per active class.
|
|
25
|
-
.ln-sort-asc [data-ln-col-sort] {
|
|
26
|
-
[data-ln-sort-icon="none"] { display: none; }
|
|
27
|
-
[data-ln-sort-icon="asc"] { display: inline-block; }
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.ln-sort-desc [data-ln-col-sort] {
|
|
31
|
-
[data-ln-sort-icon="none"] { display: none; }
|
|
32
|
-
[data-ln-sort-icon="desc"] { display: inline-block; }
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// ─── Filter button ────────────────────────────────────────
|
|
36
|
-
|
|
37
|
-
[data-ln-col-filter] {
|
|
38
|
-
@include data-table-filter-button;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
th:hover [data-ln-col-filter] {
|
|
42
|
-
opacity: 0.7;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.ln-filter-active {
|
|
46
|
-
@include data-table-filter-active;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// ─── Filter dropdown ──────────────────────────────────────
|
|
50
|
-
|
|
51
|
-
.column-filter-dropdown {
|
|
52
|
-
@include data-table-filter-dropdown;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// ─── Row action buttons ─────────────────────────────────
|
|
56
|
-
|
|
57
|
-
[data-ln-row-action] {
|
|
58
|
-
@include data-table-row-action;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
[data-ln-row-action="delete"] {
|
|
62
|
-
@include data-table-row-action-delete;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// ─── Row interaction states ─────────────────────────────
|
|
66
|
-
|
|
67
|
-
[data-ln-row] {
|
|
68
|
-
@include data-table-row;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.ln-row-selected {
|
|
72
|
-
@include data-table-row-selected;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.ln-row-focused {
|
|
76
|
-
@include data-table-row-focused;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// ─── Virtual-scroll spacer ──────────────────────────────
|
|
80
|
-
|
|
81
|
-
.ln-data-table__spacer {
|
|
82
|
-
@include data-table-spacer-row;
|
|
83
|
-
}
|