@livenetworks/ashlar 1.3.3 → 1.4.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/js/ln-accordion/ln-accordion.js +1 -1
- package/js/ln-api-connector/ln-api-connector.js +1 -1
- package/js/ln-autoresize/ln-autoresize.js +1 -1
- package/js/ln-autosave/ln-autosave.js +1 -1
- package/js/ln-circular-progress/ln-circular-progress.js +1 -1
- package/js/ln-confirm/ln-confirm.js +1 -1
- package/js/ln-core/helpers.js +45 -0
- package/js/ln-core/index.js +1 -1
- package/js/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
- package/js/ln-data-coordinator/ln-data-coordinator.js +1 -1
- package/js/ln-data-store/ln-data-store.js +1 -1
- package/js/ln-data-table/ln-data-table.js +1 -1
- package/js/ln-date/README.md +11 -1
- package/js/ln-date/ln-date.js +1 -1
- package/js/ln-date/src/ln-date.js +104 -1
- package/js/ln-dropdown/ln-dropdown.js +1 -1
- package/js/ln-filter/ln-filter.js +1 -1
- package/js/ln-form/ln-form.js +1 -1
- package/js/ln-modal/ln-modal.js +1 -1
- package/js/ln-number/ln-number.js +1 -1
- package/js/ln-number/src/ln-number.js +50 -2
- package/js/ln-popover/ln-popover.js +1 -1
- package/js/ln-search/ln-search.js +1 -1
- package/js/ln-sortable/ln-sortable.js +1 -1
- package/js/ln-table/ln-table.js +1 -1
- package/js/ln-tabs/ln-tabs.js +1 -1
- package/js/ln-time/ln-time.js +1 -1
- package/js/ln-toggle/ln-toggle.js +1 -1
- package/js/ln-tooltip/ln-tooltip.js +1 -1
- package/js/ln-translations/ln-translations.js +1 -1
- package/js/ln-validate/ln-validate.js +1 -1
- package/package.json +55 -55
- package/scss/components/_date.scss +21 -0
- package/scss/config/mixins/_form.scss +101 -54
- package/scss/config/mixins/_layout.scss +7 -9
- package/scss/ln-ashlar.scss +1 -0
|
@@ -25,9 +25,12 @@
|
|
|
25
25
|
--margin-block: var(--size-xs);
|
|
26
26
|
margin-bottom: var(--margin-block);
|
|
27
27
|
|
|
28
|
-
// Required indicator — red * after label text
|
|
29
|
-
//
|
|
30
|
-
|
|
28
|
+
// Required indicator — red * after label text.
|
|
29
|
+
// Supports standard wrapping classes/tags (.form-element, .form-group, label)
|
|
30
|
+
// and general siblings preceding a required input.
|
|
31
|
+
:is(.form-element, .form-group, .form-field):has([required]) > &,
|
|
32
|
+
label:has([required]) &,
|
|
33
|
+
&:has(~ :is(input, select, textarea)[required]) {
|
|
31
34
|
&::after {
|
|
32
35
|
content: ' *';
|
|
33
36
|
color: hsl(var(--color-error));
|
|
@@ -141,82 +144,126 @@
|
|
|
141
144
|
padding-right: 2.5rem;
|
|
142
145
|
}
|
|
143
146
|
|
|
144
|
-
// ───
|
|
147
|
+
// ─── Field group — generic bordered flex shell ────────────────────
|
|
145
148
|
//
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
// <input type="…">
|
|
150
|
-
// <svg class="ln-icon"/> ← trailing icon (optional)
|
|
151
|
-
// </label>
|
|
149
|
+
// One mixin for any control that is a bordered shell wrapping a row of
|
|
150
|
+
// children: a leading/trailing icon, the input (or select), and/or an
|
|
151
|
+
// interactive button (search submit, date-picker trigger).
|
|
152
152
|
//
|
|
153
|
-
//
|
|
154
|
-
//
|
|
155
|
-
//
|
|
156
|
-
//
|
|
157
|
-
// padding and fights the wrapper — see the asymmetric spacing that
|
|
158
|
-
// motivated this mixin.
|
|
153
|
+
// <label> <span data-ln-date-field>
|
|
154
|
+
// <svg class="ln-icon"/> <input type="text" …>
|
|
155
|
+
// <input …> <button>…</button>
|
|
156
|
+
// </label> </span>
|
|
159
157
|
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
158
|
+
// The wrapper is the VISUAL SHELL only: form-input supplies border, bg,
|
|
159
|
+
// radius, transition; the mixin adds flex layout and zeroes the shell's
|
|
160
|
+
// own padding. Each child owns its padding. Children strip only the chrome
|
|
161
|
+
// the shell now owns (border, bg, box-shadow). Focus is handled once on the
|
|
162
|
+
// shell via :focus-within; children suppress their own focus ring.
|
|
163
|
+
//
|
|
164
|
+
// Applied via semantic selectors (no class on the wrapper):
|
|
165
|
+
// - components/_form.scss → label:has(.ln-icon):has(text input)
|
|
166
|
+
// - components/_date.scss → [data-ln-date-field]
|
|
162
167
|
|
|
163
|
-
@mixin form-
|
|
164
|
-
@include
|
|
168
|
+
@mixin form-field-group {
|
|
169
|
+
@include form-input; // visual shell: border, bg, radius, transition, outline
|
|
170
|
+
@include inline-flex; // override form-input's block display
|
|
165
171
|
@include items-center;
|
|
166
|
-
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
padding: var(--padding-y) var(--padding-x);
|
|
172
|
-
background: var(--color-bg);
|
|
173
|
-
@include border;
|
|
174
|
-
border-radius: var(--radius);
|
|
175
|
-
@include transition;
|
|
176
|
-
font-size: var(--font-size);
|
|
177
|
-
line-height: var(--line-height);
|
|
178
|
-
// Wrapping-label reset: undo form-label defaults that would otherwise leak.
|
|
179
|
-
margin-bottom: 0;
|
|
172
|
+
position: relative; // anchors any absolute-positioned children (e.g. native pickers)
|
|
173
|
+
overflow: hidden; // clips child corners to the shell's border-radius automatically
|
|
174
|
+
width: auto; // cancel form-input's w-full
|
|
175
|
+
padding: 0; // shell owns NO padding; children manage their own
|
|
176
|
+
margin-bottom: 0; // defensive: wrapping <label> carries form-label margin
|
|
180
177
|
|
|
181
178
|
&:focus-within {
|
|
182
179
|
@include _form-focus-style;
|
|
180
|
+
|
|
181
|
+
> input,
|
|
182
|
+
> select {
|
|
183
|
+
box-shadow: none; // suppress child's own form-input focus ring
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Propagate validation states to the parent visual shell
|
|
188
|
+
&:has(> .ln-validate-invalid) {
|
|
189
|
+
@include form-validate-invalid;
|
|
190
|
+
}
|
|
191
|
+
&:has(> .ln-validate-valid) {
|
|
192
|
+
@include form-validate-valid;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Propagate disabled states to the parent visual shell
|
|
196
|
+
&:has(> input:disabled),
|
|
197
|
+
&:has(> select:disabled),
|
|
198
|
+
&:has(> button:disabled) {
|
|
199
|
+
@include opacity-50;
|
|
200
|
+
@include cursor-not-allowed;
|
|
201
|
+
--color-bg: var(--bg-sunken);
|
|
202
|
+
background: var(--color-bg);
|
|
203
|
+
|
|
204
|
+
* {
|
|
205
|
+
@include cursor-not-allowed;
|
|
206
|
+
}
|
|
183
207
|
}
|
|
184
208
|
|
|
185
209
|
> .ln-icon {
|
|
186
210
|
@include flex-shrink-0;
|
|
211
|
+
padding: var(--size-xs) var(--size-sm); // icon provides its own row spacing
|
|
187
212
|
--color-fg: var(--fg-subtle);
|
|
188
213
|
color: var(--color-fg);
|
|
189
214
|
}
|
|
190
215
|
|
|
191
|
-
> input
|
|
192
|
-
|
|
193
|
-
|
|
216
|
+
> input,
|
|
217
|
+
> select {
|
|
218
|
+
// form-input is already applied globally — strip only shell-owned chrome.
|
|
194
219
|
@include border-none;
|
|
195
220
|
background: transparent;
|
|
196
|
-
outline: none;
|
|
197
221
|
box-shadow: none;
|
|
198
|
-
|
|
199
|
-
// Tighten leading for a single-line control. form-input inherits
|
|
200
|
-
// --lh-body-md (1.6) which is tuned for prose readability, not form
|
|
201
|
-
// controls — that leaves ~7px of wasted leading above and below the
|
|
202
|
-
// glyph inside the input's own line box, which compounds with the
|
|
203
|
-
// label's padding and makes icon-group feel airy. 1.25 keeps
|
|
204
|
-
// descenders (g/p/j/y) safe and brings the label down to ~36px total.
|
|
205
|
-
line-height: 1.25;
|
|
206
|
-
|
|
207
|
-
// Take the remaining flex space. width: auto cancels form-input's
|
|
208
|
-
// width: 100%; flex-1 + min-width: 0 lets the field shrink below
|
|
209
|
-
// its intrinsic min-content inside a narrow label.
|
|
210
222
|
width: auto;
|
|
211
223
|
@include flex-1;
|
|
212
224
|
min-width: 0;
|
|
213
225
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
226
|
+
// Tighten inner padding when adjacent to icons or buttons inside the group
|
|
227
|
+
&:not(:first-child) {
|
|
228
|
+
padding-left: var(--size-xs);
|
|
217
229
|
}
|
|
230
|
+
&:not(:last-child) {
|
|
231
|
+
padding-right: var(--size-xs);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
218
234
|
|
|
219
|
-
|
|
235
|
+
> button {
|
|
236
|
+
@include button-base;
|
|
237
|
+
@include flex-shrink-0;
|
|
238
|
+
@include border-none;
|
|
239
|
+
align-self: stretch;
|
|
240
|
+
display: inline-flex;
|
|
241
|
+
align-items: center;
|
|
242
|
+
justify-content: center;
|
|
243
|
+
padding-top: 0;
|
|
244
|
+
padding-bottom: 0;
|
|
245
|
+
// Tighter horizontal padding for icon-only button inside groups to keep it compact and squarish
|
|
246
|
+
padding-left: var(--size-sm);
|
|
247
|
+
padding-right: var(--size-sm);
|
|
248
|
+
border-radius: 0; // Square the button to sit flush with the input border
|
|
249
|
+
|
|
250
|
+
> .ln-icon {
|
|
251
|
+
--color-fg: var(--fg-subtle);
|
|
252
|
+
color: var(--color-fg);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// ─── Icon input group — search/icon field (thin wrapper) ──────────
|
|
258
|
+
//
|
|
259
|
+
// form-field-group + the search-clear control, which is the only piece
|
|
260
|
+
// unique to this binding.
|
|
261
|
+
|
|
262
|
+
@mixin form-input-icon-group {
|
|
263
|
+
@include form-field-group;
|
|
264
|
+
|
|
265
|
+
> input {
|
|
266
|
+
// Hide the clear button while the field is empty.
|
|
220
267
|
&:placeholder-shown ~ [data-ln-search-clear] {
|
|
221
268
|
@include hidden;
|
|
222
269
|
}
|
|
@@ -4,11 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
// Layout — grid, stack, container
|
|
6
6
|
|
|
7
|
-
@mixin
|
|
7
|
+
@mixin _grid-base {
|
|
8
8
|
display: grid;
|
|
9
9
|
--gap: var(--size-lg);
|
|
10
10
|
gap: var(--gap);
|
|
11
11
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@mixin grid {
|
|
15
|
+
@include _grid-base;
|
|
12
16
|
|
|
13
17
|
@include mq-up(md) {
|
|
14
18
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
@@ -20,10 +24,7 @@
|
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
@mixin grid-2 {
|
|
23
|
-
|
|
24
|
-
--gap: var(--size-lg);
|
|
25
|
-
gap: var(--gap);
|
|
26
|
-
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
27
|
+
@include _grid-base;
|
|
27
28
|
|
|
28
29
|
@include mq-up(md) {
|
|
29
30
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
@@ -31,10 +32,7 @@
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
@mixin grid-4 {
|
|
34
|
-
|
|
35
|
-
--gap: var(--size-lg);
|
|
36
|
-
gap: var(--gap);
|
|
37
|
-
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
35
|
+
@include _grid-base;
|
|
38
36
|
|
|
39
37
|
@include mq-up(md) {
|
|
40
38
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|