@guildofgleks/ui 21.5.2 → 21.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/AGENTS.md +29 -1
- package/CHANGELOG.md +123 -0
- package/README.md +4 -0
- package/fesm2022/guildofgleks-ui.mjs +73 -8
- package/fesm2022/guildofgleks-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/styles/button.css +19 -2
- package/styles/menu.css +13 -3
- package/styles/utilities.css +37 -1
- package/types/guildofgleks-ui.d.ts +50 -3
package/package.json
CHANGED
package/styles/button.css
CHANGED
|
@@ -67,7 +67,24 @@
|
|
|
67
67
|
color var(--gog-button-transition-duration) var(--gog-easing);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
/*
|
|
71
|
+
* The doubled class on this rule and the disabled one below is deliberate, and the only two
|
|
72
|
+
* rules in this file that need it.
|
|
73
|
+
*
|
|
74
|
+
* `[gogButton]` goes on the *consumer's* own element, which is the element they style — and
|
|
75
|
+
* Angular's emulated encapsulation stamps `[_ngcontent-…]` onto every rule in a component
|
|
76
|
+
* stylesheet, so an ordinary `.my-btn { cursor: pointer }` is (0,2,0). That exactly ties
|
|
77
|
+
* `.gog-btn:disabled` and wins on source order, because this file loads before the app's own
|
|
78
|
+
* styles. Measured in the showcase: a disabled button went from `not-allowed`/`0.4` to
|
|
79
|
+
* `pointer`/`1` under a single-class consumer rule — it looked and felt enabled while disabled.
|
|
80
|
+
*
|
|
81
|
+
* `:hover` and `:active` below need no help: their `:not(:disabled)` already makes them (0,3,0).
|
|
82
|
+
* The base `.gog-btn` is left beatable on purpose — restyling the look is the consumer's call.
|
|
83
|
+
* These two are not look, they are state and focus visibility, and losing them silently is a
|
|
84
|
+
* correctness and accessibility regression rather than a taste one. A consumer who genuinely
|
|
85
|
+
* wants to restyle them can still do it by being specific about it.
|
|
86
|
+
*/
|
|
87
|
+
.gog-btn.gog-btn:focus-visible {
|
|
71
88
|
outline: var(--gog-button-focus-ring-width) solid
|
|
72
89
|
var(
|
|
73
90
|
--gog-button-hover-bg,
|
|
@@ -114,7 +131,7 @@
|
|
|
114
131
|
}
|
|
115
132
|
}
|
|
116
133
|
|
|
117
|
-
.gog-btn:disabled {
|
|
134
|
+
.gog-btn.gog-btn:disabled {
|
|
118
135
|
opacity: var(--gog-button-disabled-opacity);
|
|
119
136
|
cursor: not-allowed;
|
|
120
137
|
}
|
package/styles/menu.css
CHANGED
|
@@ -74,18 +74,28 @@
|
|
|
74
74
|
transition: background-color var(--gog-menu-transition-duration) var(--gog-easing);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/*
|
|
78
|
+
* Doubled class on the `:focus-visible` and `:disabled` rules, for the reason spelled out in
|
|
79
|
+
* `button.css`: a menu item is the consumer's own `<button>`, so an ordinary single-class rule
|
|
80
|
+
* in their component stylesheet ties these at (0,2,0) and wins on source order. The `:hover`
|
|
81
|
+
* selector is already (0,3,0) through its `:not(:disabled)` and is left alone.
|
|
82
|
+
*
|
|
83
|
+
* It matters more here than for a button. The arrow keys step over a disabled item, so an item
|
|
84
|
+
* that has lost its disabled styling is one the pointer can still see as ordinary while the
|
|
85
|
+
* keyboard refuses to reach it — the two input methods disagreeing about what exists.
|
|
86
|
+
*/
|
|
77
87
|
.gog-menu__item:hover:not(:disabled),
|
|
78
|
-
.gog-menu__item:focus-visible {
|
|
88
|
+
.gog-menu__item.gog-menu__item:focus-visible {
|
|
79
89
|
background-color: var(--gog-menu-item-hover-bg);
|
|
80
90
|
color: var(--gog-menu-item-hover-color);
|
|
81
91
|
}
|
|
82
92
|
|
|
83
|
-
.gog-menu__item:focus-visible {
|
|
93
|
+
.gog-menu__item.gog-menu__item:focus-visible {
|
|
84
94
|
outline: var(--gog-menu-focus-ring-width) solid var(--gog-menu-focus-ring);
|
|
85
95
|
outline-offset: calc(var(--gog-menu-focus-ring-width) * -1);
|
|
86
96
|
}
|
|
87
97
|
|
|
88
|
-
.gog-menu__item:disabled {
|
|
98
|
+
.gog-menu__item.gog-menu__item:disabled {
|
|
89
99
|
color: var(--gog-menu-item-disabled-color);
|
|
90
100
|
opacity: var(--gog-menu-item-disabled-opacity);
|
|
91
101
|
cursor: not-allowed;
|
package/styles/utilities.css
CHANGED
|
@@ -19,6 +19,31 @@
|
|
|
19
19
|
--gog-direction-sign: 1;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/*
|
|
23
|
+
* Every element the library renders sizes itself border-box, so the package does not depend on
|
|
24
|
+
* the consumer having a `* { box-sizing: border-box }` reset.
|
|
25
|
+
*
|
|
26
|
+
* It used to. `.gog-input__field` is `width: 100%` plus horizontal padding plus a border, so
|
|
27
|
+
* under the CSS default of `content-box` it overflowed its own container by exactly that much —
|
|
28
|
+
* measured 20px at `xsm` rising to 48px at `slg`. It stayed invisible for the life of the
|
|
29
|
+
* package because both apps that render it (`ui-showcase`, and `gleks-ui-lab` since later) carry
|
|
30
|
+
* a global reset of their own, so the library was only ever *looked at* under border-box.
|
|
31
|
+
*
|
|
32
|
+
* Matched on the class prefix rather than by listing elements, because the set that needs it is
|
|
33
|
+
* exactly "things the library painted" — including the ones that live on a consumer's own
|
|
34
|
+
* element (`.gog-btn`, `.gog-menu__item`, `.gog-collapsible__trigger`) and would be missed by a
|
|
35
|
+
* `gog-*` tag list. A consumer's own elements are untouched.
|
|
36
|
+
*
|
|
37
|
+
* Specificity is a single class, deliberately: this is a default the library needs, not a
|
|
38
|
+
* decision it should win. `:where()` would drop it to zero and lose to the UA's own
|
|
39
|
+
* `content-box`… which is not a thing, but it would also lose to a consumer's `*` reset setting
|
|
40
|
+
* `content-box` back, and matching that intent is right.
|
|
41
|
+
*/
|
|
42
|
+
[class^='gog-'],
|
|
43
|
+
[class*=' gog-'] {
|
|
44
|
+
box-sizing: border-box;
|
|
45
|
+
}
|
|
46
|
+
|
|
22
47
|
[dir='rtl'] {
|
|
23
48
|
--gog-inline-start-side: right;
|
|
24
49
|
--gog-inline-end-side: left;
|
|
@@ -171,7 +196,18 @@
|
|
|
171
196
|
cursor: pointer;
|
|
172
197
|
}
|
|
173
198
|
|
|
174
|
-
|
|
199
|
+
/*
|
|
200
|
+
* Scoped through the host on purpose, for one point of specificity the plain
|
|
201
|
+
* `.gog-collapsible__trigger[aria-disabled='true']` (0,2,0) does not have.
|
|
202
|
+
*
|
|
203
|
+
* The trigger is the *consumer's* element, and Angular's emulated encapsulation stamps
|
|
204
|
+
* `[_ngcontent-…]` onto every rule in a component stylesheet — so an ordinary
|
|
205
|
+
* `.my-trigger { cursor: pointer }` in the consumer's own component is also (0,2,0) and wins on
|
|
206
|
+
* source order, since this file loads before their app's styles. Measured: a disabled trigger
|
|
207
|
+
* reading `cursor: pointer` while this rule's `opacity` applied, in the showcase's own demo.
|
|
208
|
+
* A disabled state the consumer has to know to opt out of is not a disabled state.
|
|
209
|
+
*/
|
|
210
|
+
gog-collapsible .gog-collapsible__trigger[aria-disabled='true'] {
|
|
175
211
|
cursor: not-allowed;
|
|
176
212
|
opacity: var(--gog-collapsible-disabled-opacity);
|
|
177
213
|
}
|
|
@@ -282,7 +282,7 @@ declare class AccordionComponent {
|
|
|
282
282
|
* Left unset by default since not every accordion instance represents document structure
|
|
283
283
|
* (e.g. one nested inside a card).
|
|
284
284
|
*/
|
|
285
|
-
readonly headingLevel: _angular_core.InputSignal<2 |
|
|
285
|
+
readonly headingLevel: _angular_core.InputSignal<2 | 4 | 3 | 5 | 6 | undefined>;
|
|
286
286
|
/**
|
|
287
287
|
* Two-way bindable set of currently open item ids. Exposed as a model so consumers
|
|
288
288
|
* can drive the accordion externally (e.g. `[(openIds)]="mySet"`) instead of only
|
|
@@ -310,6 +310,15 @@ declare class AccordionComponent {
|
|
|
310
310
|
*/
|
|
311
311
|
private readonly autoExpanded;
|
|
312
312
|
protected readonly skeletonRows: _angular_core.Signal<number[]>;
|
|
313
|
+
/**
|
|
314
|
+
* Placeholder title widths, cycled by row index.
|
|
315
|
+
*
|
|
316
|
+
* Every bar used to be 55%, which reads as a repeating progress artifact rather than as text
|
|
317
|
+
* that has not arrived — real titles are not all the same length. Cycled rather than random:
|
|
318
|
+
* a random width would differ between the server-rendered pass and hydration, and would make
|
|
319
|
+
* every snapshot of this component unstable.
|
|
320
|
+
*/
|
|
321
|
+
protected skeletonWidth(index: number): string;
|
|
313
322
|
constructor();
|
|
314
323
|
protected isOpen(id: string | number): boolean;
|
|
315
324
|
protected toggle(item: GogAccordionItem): void;
|
|
@@ -935,6 +944,18 @@ declare class AutocompleteComponent<TOption = GogDropdownOption, TValue = string
|
|
|
935
944
|
protected readonly visibleOptions: _angular_core.Signal<TOption[]>;
|
|
936
945
|
protected readonly activeOptionId: _angular_core.Signal<string | null>;
|
|
937
946
|
private searchTimer;
|
|
947
|
+
/**
|
|
948
|
+
* True from the first keystroke until the edit is resolved — by blur, Escape, picking an
|
|
949
|
+
* option, or the clear button. Deliberately a plain field, not a signal: the sync effect below
|
|
950
|
+
* must not re-run when it changes, only consult it.
|
|
951
|
+
*
|
|
952
|
+
* It exists because the effect used to use `!isOpen()` to mean "the user is not mid-edit", and
|
|
953
|
+
* the panel closes for reasons that are not that. Backspacing the last character takes the text
|
|
954
|
+
* under `minLength`, which closes the panel — so the effect fired and wrote the selected label
|
|
955
|
+
* straight back into the field. Nine backspaces on "Amsterdam" left "Amsterdam": the field
|
|
956
|
+
* could not be cleared at all while a selection was held.
|
|
957
|
+
*/
|
|
958
|
+
private editing;
|
|
938
959
|
constructor();
|
|
939
960
|
protected isSelected(option: TOption): boolean;
|
|
940
961
|
protected onInput(event: Event): void;
|
|
@@ -3671,8 +3692,34 @@ declare class TableComponent<T extends object> {
|
|
|
3671
3692
|
readonly loading: _angular_core.InputSignal<boolean>;
|
|
3672
3693
|
/** Show vertical borders between columns */
|
|
3673
3694
|
readonly showColumnBorders: _angular_core.InputSignal<boolean>;
|
|
3674
|
-
/**
|
|
3695
|
+
/**
|
|
3696
|
+
* Stick the header row to the top of the table's own scroll viewport.
|
|
3697
|
+
*
|
|
3698
|
+
* **Needs `maxHeight` to be reliable.** A sticky element resolves against its nearest scroll
|
|
3699
|
+
* container, and the table wraps itself in a `gog-scroll`; the moment that scroller starts
|
|
3700
|
+
* scrolling sideways it is a scroll container on both axes — CSS coerces `overflow-y: visible`
|
|
3701
|
+
* to `auto` beside a scrolling `overflow-x`, and `clip` to `hidden`, so there is no value that
|
|
3702
|
+
* scrolls one axis and stays out of the sticky chain on the other. Without `maxHeight` that
|
|
3703
|
+
* viewport is exactly as tall as its content and never scrolls vertically, so a header pinned
|
|
3704
|
+
* to it rides out of view along with everything else.
|
|
3705
|
+
*
|
|
3706
|
+
* With `maxHeight` set the viewport is the vertical scrollport, and the header pins to it.
|
|
3707
|
+
*/
|
|
3675
3708
|
readonly stickyHeader: _angular_core.InputSignal<boolean>;
|
|
3709
|
+
/**
|
|
3710
|
+
* Caps the table's own scroll viewport, in any CSS length — `'420px'`, `'60vh'`. The table then
|
|
3711
|
+
* owns its vertical scrolling instead of growing to its content and letting an ancestor scroll
|
|
3712
|
+
* it, which is what makes `stickyHeader` work (see above).
|
|
3713
|
+
*
|
|
3714
|
+
* An input rather than a `--gog-table-*` token, even though the value only ever lands in CSS:
|
|
3715
|
+
* it also decides whether the internal scroller handles the vertical axis at all. A capped
|
|
3716
|
+
* viewport has to scroll vertically; an uncapped one must *not* become a scroll container,
|
|
3717
|
+
* because that would put every table in the sticky chain of its own descendants and take the
|
|
3718
|
+
* consumer's own scrolling region out of it. That is behaviour, not appearance.
|
|
3719
|
+
*
|
|
3720
|
+
* `null` leaves the table exactly as it was: viewport at content height, vertical axis inert.
|
|
3721
|
+
*/
|
|
3722
|
+
readonly maxHeight: _angular_core.InputSignal<string | null>;
|
|
3676
3723
|
/** Row density: lg (default) / md (compact) / sm (dense) */
|
|
3677
3724
|
readonly size: _angular_core.InputSignal<GogSize>;
|
|
3678
3725
|
/**
|
|
@@ -3782,7 +3829,7 @@ declare class TableComponent<T extends object> {
|
|
|
3782
3829
|
/** CSS grid-area for the pagination block */
|
|
3783
3830
|
readonly paginatorGridArea: _angular_core.Signal<"left" | "right" | "center">;
|
|
3784
3831
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableComponent<any>, never>;
|
|
3785
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableComponent<any>, "gog-table", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "fullWidth": { "alias": "fullWidth"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "showPageSizeSelect": { "alias": "showPageSizeSelect"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "lazy": { "alias": "lazy"; "required": false; "isSignal": true; }; "totalRecords": { "alias": "totalRecords"; "required": false; "isSignal": true; }; "interactiveRows": { "alias": "interactiveRows"; "required": false; "isSignal": true; }; "selectionMode": { "alias": "selectionMode"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "dataKey": { "alias": "dataKey"; "required": false; "isSignal": true; }; "showSelectionColumn": { "alias": "showSelectionColumn"; "required": false; "isSignal": true; }; "showRowNumbers": { "alias": "showRowNumbers"; "required": false; "isSignal": true; }; "showTotal": { "alias": "showTotal"; "required": false; "isSignal": true; }; "emptyPlaceholder": { "alias": "emptyPlaceholder"; "required": false; "isSignal": true; }; "paginatorPosition": { "alias": "paginatorPosition"; "required": false; "isSignal": true; }; "totalPosition": { "alias": "totalPosition"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "showColumnBorders": { "alias": "showColumnBorders"; "required": false; "isSignal": true; }; "stickyHeader": { "alias": "stickyHeader"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, { "pageSize": "pageSizeChange"; "selection": "selectionChange"; "gogSortChange": "gogSortChange"; "gogPageChange": "gogPageChange"; "gogRowClick": "gogRowClick"; }, ["columns"], never, true, never>;
|
|
3832
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableComponent<any>, "gog-table", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "fullWidth": { "alias": "fullWidth"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "showPageSizeSelect": { "alias": "showPageSizeSelect"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "lazy": { "alias": "lazy"; "required": false; "isSignal": true; }; "totalRecords": { "alias": "totalRecords"; "required": false; "isSignal": true; }; "interactiveRows": { "alias": "interactiveRows"; "required": false; "isSignal": true; }; "selectionMode": { "alias": "selectionMode"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "dataKey": { "alias": "dataKey"; "required": false; "isSignal": true; }; "showSelectionColumn": { "alias": "showSelectionColumn"; "required": false; "isSignal": true; }; "showRowNumbers": { "alias": "showRowNumbers"; "required": false; "isSignal": true; }; "showTotal": { "alias": "showTotal"; "required": false; "isSignal": true; }; "emptyPlaceholder": { "alias": "emptyPlaceholder"; "required": false; "isSignal": true; }; "paginatorPosition": { "alias": "paginatorPosition"; "required": false; "isSignal": true; }; "totalPosition": { "alias": "totalPosition"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "showColumnBorders": { "alias": "showColumnBorders"; "required": false; "isSignal": true; }; "stickyHeader": { "alias": "stickyHeader"; "required": false; "isSignal": true; }; "maxHeight": { "alias": "maxHeight"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, { "pageSize": "pageSizeChange"; "selection": "selectionChange"; "gogSortChange": "gogSortChange"; "gogPageChange": "gogPageChange"; "gogRowClick": "gogRowClick"; }, ["columns"], never, true, never>;
|
|
3786
3833
|
}
|
|
3787
3834
|
|
|
3788
3835
|
declare class SpinnerComponent {
|