@livenetworks/ashlar 1.4.0 → 1.5.1

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.
Files changed (44) hide show
  1. package/js/ln-accordion/ln-accordion.js +1 -1
  2. package/js/ln-api-connector/ln-api-connector.js +1 -1
  3. package/js/ln-autoresize/ln-autoresize.js +1 -1
  4. package/js/ln-autosave/ln-autosave.js +1 -1
  5. package/js/ln-circular-progress/ln-circular-progress.js +1 -1
  6. package/js/ln-confirm/ln-confirm.js +1 -1
  7. package/js/ln-core/helpers.js +6 -3
  8. package/js/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
  9. package/js/ln-data-coordinator/ln-data-coordinator.js +1 -1
  10. package/js/ln-data-store/ln-data-store.js +1 -1
  11. package/js/ln-data-table/ln-data-table.js +1 -1
  12. package/js/ln-data-table/src/ln-data-table.js +0 -16
  13. package/js/ln-date/ln-date.js +1 -1
  14. package/js/ln-dropdown/ln-dropdown.js +1 -1
  15. package/js/ln-filter/README.md +99 -99
  16. package/js/ln-filter/ln-filter.js +1 -1
  17. package/js/ln-form/ln-form.js +1 -1
  18. package/js/ln-modal/ln-modal.js +1 -1
  19. package/js/ln-number/ln-number.js +1 -1
  20. package/js/ln-popover/ln-popover.js +1 -1
  21. package/js/ln-search/ln-search.js +1 -1
  22. package/js/ln-sortable/ln-sortable.js +1 -1
  23. package/js/ln-table/ln-table-sort.js +1 -1
  24. package/js/ln-table/ln-table.js +1 -1
  25. package/js/ln-table/src/ln-table-sort.js +156 -168
  26. package/js/ln-tabs/ln-tabs.js +1 -1
  27. package/js/ln-time/ln-time.js +1 -1
  28. package/js/ln-toggle/ln-toggle.js +1 -1
  29. package/js/ln-tooltip/ln-tooltip.js +1 -1
  30. package/js/ln-translations/ln-translations.js +1 -1
  31. package/js/ln-validate/ln-validate.js +1 -1
  32. package/package.json +3 -2
  33. package/scss/components/_filter.scss +25 -0
  34. package/scss/components/_ln-table.scss +1 -2
  35. package/scss/components/_table.scss +55 -1
  36. package/scss/config/mixins/_diagnostics.scss +37 -0
  37. package/scss/config/mixins/_filter.scss +49 -0
  38. package/scss/config/mixins/_index.scss +2 -1
  39. package/scss/config/mixins/_ln-table.scss +10 -91
  40. package/scss/config/mixins/_table.scss +202 -33
  41. package/scss/ln-ashlar-dev.scss +21 -0
  42. package/scss/ln-ashlar.scss +1 -1
  43. package/scss/components/_data-table.scss +0 -83
  44. package/scss/config/mixins/_data-table.scss +0 -346
@@ -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
- }
@@ -1,346 +0,0 @@
1
- @use 'display' as *;
2
- @use 'spacing' as *;
3
- @use 'sizing' as *;
4
- @use 'typography' as *;
5
- @use 'colors' as *;
6
- @use 'borders' as *;
7
- @use 'shadows' as *;
8
- @use 'position' as *;
9
- @use 'transitions' as *;
10
- @use 'interaction' as *;
11
- @use 'motion' as *;
12
- @use 'form' as *;
13
- @use 'btn' as *;
14
- @use 'card' as *;
15
- @use 'ln-table';
16
-
17
- // Data Table -- enhanced table with toolbar, sort, filter, virtual scroll.
18
- //
19
- // Usage:
20
- // [data-ln-data-table] { @include data-table; }
21
- //
22
- // State-driven CSS (loading, selected, focused, spacer) stays in
23
- // the co-located JS SCSS file.
24
-
25
- @mixin data-table {
26
- @include relative;
27
-
28
- // Row hover token — local to data-table so chrome (toolbar, thead,
29
- // footer) reading --bg-sunken stays visually distinct from the row
30
- // the cursor is on. --bg-elevated is unsuitable: it equals --bg-base
31
- // in light theme, making hover invisible. Derive a 4-point lightness
32
- // step from --bg-base via CSS relative color syntax (number form, see
33
- // _btn.scss header for percentage-vs-number rationale).
34
- //
35
- // Light theme: hsl(white) → ~hsl(0 0% 96%)
36
- // Dark theme: hsl(220 16% 13%) → hsl(220 16% 17%) ≈ --bg-elevated dark
37
- //
38
- // The 4-point step is monotonically distinct from --bg-sunken
39
- // (light: neutral-100 ≈ 95%; dark: 220 16% 20%) on both sides.
40
- --bg-row-hover: hsl(from var(--bg-base) h s calc(l - 4));
41
-
42
- // Override @mixin table-base's `tbody tr:hover` to use the local hover
43
- // token instead of --bg-sunken. Default hover stays --bg-sunken for
44
- // standalone tables; data-table re-binds so its hover disambiguates from
45
- // chrome that also uses --bg-sunken.
46
- > table tbody tr:hover {
47
- --color-bg: var(--bg-row-hover);
48
- background: var(--color-bg);
49
- }
50
-
51
- // Inner table — `border-collapse: separate` + `border-spacing: 0` is
52
- // required for `position: sticky` on `<thead> th` to actually pin in
53
- // Chrome. With the `border-collapse: collapse` that `@mixin table-base`
54
- // sets by default, Chrome silently drops sticky behavior on table cells —
55
- // the same reason `@mixin ln-table` applies this exact override. Borders
56
- // are restored cell-by-cell via table-base's `td { @include border-b }`,
57
- // so no visual change.
58
- > table {
59
- border-collapse: separate;
60
- border-spacing: 0;
61
- }
62
-
63
-
64
-
65
- // Sticky header - Pins the entire thead (including the in-thead toolbar) at top:0
66
- thead {
67
- @include sticky-top;
68
- }
69
-
70
- thead th {
71
- position: relative;
72
- top: auto;
73
- z-index: auto;
74
- background: var(--bg-sunken);
75
-
76
- &[data-ln-col] {
77
- // Maintain standard table-cell layout so columns don't break or stack vertically
78
- white-space: normal;
79
-
80
- // Add padding-inline-end to prevent text from overlapping absolute buttons
81
-
82
- // Case 1: Has both sort and filter buttons
83
- &:has([data-ln-col-sort]):has([data-ln-col-filter]) {
84
- padding-inline-end: calc(var(--padding-x) + 2.5rem);
85
-
86
- [data-ln-col-filter] {
87
- position: absolute;
88
- top: 50%;
89
- transform: translateY(-50%);
90
- right: var(--padding-x);
91
- margin: 0;
92
- }
93
-
94
- [data-ln-col-sort] {
95
- position: absolute;
96
- top: 50%;
97
- transform: translateY(-50%);
98
- right: calc(var(--padding-x) + 1.25rem);
99
- margin: 0;
100
- }
101
- }
102
-
103
- // Case 2: Has only sort button
104
- &:has([data-ln-col-sort]):not(:has([data-ln-col-filter])) {
105
- padding-inline-end: calc(var(--padding-x) + 1.25rem);
106
-
107
- [data-ln-col-sort] {
108
- position: absolute;
109
- top: 50%;
110
- transform: translateY(-50%);
111
- right: var(--padding-x);
112
- margin: 0;
113
- }
114
- }
115
-
116
- // Case 3: Has only filter button
117
- &:has([data-ln-col-filter]):not(:has([data-ln-col-sort])) {
118
- padding-inline-end: calc(var(--padding-x) + 1.25rem);
119
-
120
- [data-ln-col-filter] {
121
- position: absolute;
122
- top: 50%;
123
- transform: translateY(-50%);
124
- right: var(--padding-x);
125
- margin: 0;
126
- }
127
- }
128
- }
129
- }
130
-
131
- // Support for the in-thead toolbar row inside ln-data-table
132
- thead > tr:first-child:has(> th[colspan]) > th {
133
- @include ln-table.ln-table-thead-toolbar;
134
- }
135
-
136
- // Section footer — sibling of <table>, NOT inside it. Moved out of
137
- // <tfoot> because Chromium drops sticky on table cells when a
138
- // virtual-scroll spacer <tr> sits between the data and the tfoot row.
139
- // As a section-level <footer> sticky works reliably and shares the
140
- // same scroll container as the toolbar.
141
- //
142
- // Chrome surface visually symmetric with panel-header: --bg-sunken
143
- // fill, muted fg, body-sm text, border-block-start for separation.
144
- > footer {
145
- padding: var(--padding-y) var(--padding-x);
146
- border-block-start: var(--border-block-start, var(--border-width) solid var(--color-border));
147
- --color-bg: var(--bg-sunken);
148
- background: var(--color-bg);
149
- --color-fg: var(--fg-muted);
150
- color: var(--color-fg);
151
- font-size: var(--text-body-sm);
152
- position: sticky;
153
- bottom: 0;
154
- z-index: var(--z-sticky);
155
- }
156
- }
157
-
158
- // ─── Sort indicators ──────────────────────────────────────
159
-
160
- @mixin data-table-sort-button {
161
- opacity: 0.4;
162
- @include motion-safe {
163
- transition: opacity 0.15s;
164
- }
165
- @include cursor-pointer;
166
- background: none;
167
- border: none;
168
- --btn-padding-y: var(--size-2xs);
169
- --btn-padding-x: var(--size-2xs);
170
- --margin-inline: var(--size-xs);
171
- margin-inline-start: var(--margin-inline);
172
- vertical-align: middle;
173
-
174
- // Icon-trio visibility — neutral state shows the dual-arrow icon.
175
- // Active states (.ln-sort-asc / .ln-sort-desc on ancestor <th>)
176
- // flip to a single directional icon. See component file for the
177
- // active-state overrides.
178
- [data-ln-sort-icon="asc"],
179
- [data-ln-sort-icon="desc"] {
180
- display: none;
181
- }
182
- }
183
-
184
- @mixin data-table-sort-active {
185
- opacity: 1;
186
- color: var(--color-accent);
187
- }
188
-
189
- // ─── Filter button ────────────────────────────────────────
190
-
191
- @mixin data-table-filter-button {
192
- opacity: 0.4;
193
- @include motion-safe {
194
- transition: opacity 0.15s;
195
- }
196
- @include cursor-pointer;
197
- background: none;
198
- border: none;
199
- --btn-padding-y: var(--size-2xs);
200
- --btn-padding-x: var(--size-2xs);
201
- --margin-inline: var(--size-2xs);
202
- margin-inline-start: var(--margin-inline);
203
- vertical-align: middle;
204
- @include relative;
205
- }
206
-
207
- @mixin data-table-filter-active {
208
- opacity: 1;
209
- color: var(--color-accent);
210
-
211
- &::after {
212
- content: '';
213
- @include absolute;
214
- top: 0;
215
- right: 0;
216
- width: 0.375rem;
217
- height: 0.375rem;
218
- border-radius: var(--radius-full);
219
- background: var(--color-accent);
220
- }
221
- }
222
-
223
- // ─── Row action buttons ───────────────────────────────────
224
- //
225
- // `[data-ln-row-action]` is the ln-data-table attribute for in-row
226
- // action buttons (edit, delete, custom). They're conventionally
227
- // icon-only and live in narrow `<td>` cells — full button chrome
228
- // inflates row height and visually competes with the row content.
229
- //
230
- // Style is ghost: no bg, no border, no shadow, dim opacity at rest,
231
- // full opacity on hover. Targets the BUTTON via its own attribute,
232
- // not via ancestor selectors — a `data-ln-row-action` button looks
233
- // the same anywhere.
234
-
235
- @mixin data-table-row-action {
236
- background: none;
237
- border: none;
238
- --shadow: none;
239
- --btn-padding-y: var(--size-2xs);
240
- --btn-padding-x: var(--size-2xs);
241
- opacity: 0.5;
242
- @include motion-safe {
243
- transition: opacity 0.15s;
244
- }
245
-
246
- &:hover:not(:disabled) {
247
- background: none;
248
- opacity: 1;
249
- }
250
- }
251
-
252
- // Destructive variant — semantic-color cascade via --color-primary
253
- // rebind so the icon and any confirm-state overlay both read the
254
- // same source. Applied on top of `data-table-row-action`.
255
- @mixin data-table-row-action-delete {
256
- --color-primary: var(--color-error);
257
- color: hsl(var(--color-primary));
258
- }
259
-
260
- // ─── Filter dropdown ──────────────────────────────────────
261
-
262
- @mixin data-table-filter-dropdown {
263
- @include absolute;
264
- top: 100%;
265
- left: 0;
266
- z-index: var(--z-dropdown);
267
- --color-bg: var(--bg-elevated);
268
- background: var(--color-bg);
269
- --shadow: var(--shadow-floating);
270
- border-block-start: var(--border-block-start, var(--border-width) solid var(--color-border));
271
- border-block-end: var(--border-block-end, var(--border-width) solid var(--color-border));
272
- border-inline-start: var(--border-inline-start, var(--border-width) solid var(--color-border));
273
- border-inline-end: var(--border-inline-end, var(--border-width) solid var(--color-border));
274
- border-radius: var(--radius);
275
- box-shadow: var(--shadow);
276
- --padding-y: var(--size-sm);
277
- --padding-x: var(--size-sm);
278
- padding: var(--padding-y) var(--padding-x);
279
- min-width: 12rem;
280
- max-height: 20rem;
281
- overflow-y: auto;
282
-
283
- [data-ln-filter-search] {
284
- @include form-input;
285
- width: 100%;
286
- --margin-block: var(--size-sm);
287
- margin-bottom: var(--margin-block);
288
- }
289
-
290
- ul {
291
- }
292
-
293
- li {
294
- --padding-y: var(--size-xs);
295
- padding: var(--padding-y) 0;
296
- }
297
-
298
- label {
299
- display: flex;
300
- align-items: center;
301
- gap: var(--gap);
302
- @include cursor-pointer;
303
- font-size: var(--text-sm);
304
- }
305
-
306
- [data-ln-filter-clear] {
307
- @include btn;
308
- width: 100%;
309
- --margin-block: var(--size-sm);
310
- margin-top: var(--margin-block);
311
- font-size: var(--text-sm);
312
- }
313
- }
314
-
315
- // Row interaction state — applied to JS-marked clickable rows.
316
-
317
- @mixin data-table-row {
318
- cursor: pointer;
319
-
320
- &:hover {
321
- --color-bg: var(--bg-sunken);
322
- background: var(--color-bg);
323
- }
324
- }
325
-
326
- @mixin data-table-row-selected {
327
- background: var(--color-accent-tint);
328
- }
329
-
330
- @mixin data-table-row-focused {
331
- // Derive focus from --color-accent at this scope (same hue/saturation,
332
- // lightness +8). Number form (not percentage) — see _btn.scss for the
333
- // syntax rationale.
334
- --color-accent-focus: hsl(from var(--color-accent) h s calc(l + 8));
335
- outline: 2px solid var(--color-accent-focus);
336
- outline-offset: -2px;
337
- }
338
-
339
- // Virtual-scroll spacer rows (JS-injected) — neutralize default cell padding/border.
340
-
341
- @mixin data-table-spacer-row {
342
- td {
343
- padding: 0 !important;
344
- border: none !important;
345
- }
346
- }