@guildofgleks/ui 21.3.1 → 21.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/AGENTS.md +1351 -0
- package/README.md +227 -57
- package/TOKENS.md +63 -0
- package/fesm2022/guildofgleks-ui.mjs +1246 -135
- package/fesm2022/guildofgleks-ui.mjs.map +1 -1
- package/package.json +12 -4
- package/src/styles/button.css +193 -0
- package/src/styles/index.css +2 -0
- package/src/styles/theme.css +26 -0
- package/styles/button.css +193 -0
- package/styles/fonts.css +16 -0
- package/styles/index.css +19 -0
- package/styles/presets/one-dark.css +48 -0
- package/styles/presets/one-light.css +47 -0
- package/styles/presets/slate.css +55 -0
- package/styles/theme.css +1687 -0
- package/styles/typography.css +15 -0
- package/styles/utilities.css +170 -0
- package/types/guildofgleks-ui.d.ts +901 -64
package/AGENTS.md
ADDED
|
@@ -0,0 +1,1351 @@
|
|
|
1
|
+
# @guildofgleks/ui — AI agent guide
|
|
2
|
+
|
|
3
|
+
This file is for an AI coding agent (Claude, Copilot, Cursor, etc.) helping a developer build
|
|
4
|
+
an app that **consumes** the published `@guildofgleks/ui` npm package. It is not about
|
|
5
|
+
authoring the library — if you are working inside the `gleks_web_ui` monorepo itself, read
|
|
6
|
+
`.github/instructions/*.md` instead.
|
|
7
|
+
|
|
8
|
+
Everything below reflects the library's actual source as of **`21.4.0`**. `README.md` covers the
|
|
9
|
+
same ground at a higher level — install, setup, theming, global configuration — and is accurate;
|
|
10
|
+
this file goes further, into per-component input tables, and is the one to trust for exact names,
|
|
11
|
+
types and defaults.
|
|
12
|
+
|
|
13
|
+
> **Maintainers:** this file ships inside the npm package and is the API reference an agent reads
|
|
14
|
+
> while writing code against it, so a stale table here becomes wrong code in someone else's app —
|
|
15
|
+
> silently, because nothing fails a build. **Any change to an input, output, slot, type, service
|
|
16
|
+
> method or default updates this file in the same change**, and moves the version marker in the
|
|
17
|
+
> paragraph above. See `.github/instructions/gleks-ui-library.instructions.md`, definition of
|
|
18
|
+
> done, step 9.
|
|
19
|
+
|
|
20
|
+
## Quick facts
|
|
21
|
+
|
|
22
|
+
- Angular **v21+** only (`peerDependencies` require `^21.2.0` for `@angular/core`,
|
|
23
|
+
`@angular/common`, `@angular/forms`, `@angular/platform-browser`). No support for older
|
|
24
|
+
Angular.
|
|
25
|
+
- No Angular CDK, no Material. Only runtime dependency is `tslib`.
|
|
26
|
+
- Every component is **standalone**, `ChangeDetectionStrategy.OnPush`, and built with signals —
|
|
27
|
+
`input()` / `output()` / `model()`, never `@Input()`/`@Output()` decorators, never `ngClass`/
|
|
28
|
+
`ngStyle`.
|
|
29
|
+
- **Reactive Forms only.** Every form control implements `ControlValueAccessor` and is built
|
|
30
|
+
and tested against `[formControl]` / `formControlName`. The library never imports
|
|
31
|
+
`FormsModule` and `[(ngModel)]` is untested — don't suggest it.
|
|
32
|
+
- Theming is 100% CSS custom properties (`--gog-*`) — no Sass config, no JS theme objects, no
|
|
33
|
+
build step to restyle anything.
|
|
34
|
+
- Tree-shakeable: `"sideEffects": false` and every component is a separate standalone import, so
|
|
35
|
+
importing `ButtonComponent` alone does not pull in the rest of the library.
|
|
36
|
+
- SSR-safe: anything touching `window`/`document` is guarded with `isPlatformBrowser`/
|
|
37
|
+
`afterNextRender`.
|
|
38
|
+
|
|
39
|
+
## Install & setup
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @guildofgleks/ui
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Add the baseline stylesheet once — it carries every token the components read plus their
|
|
46
|
+
utility classes, so without it components render unstyled:
|
|
47
|
+
|
|
48
|
+
```jsonc
|
|
49
|
+
// angular.json → projects.<app>.architect.build.options
|
|
50
|
+
"styles": [
|
|
51
|
+
"node_modules/@guildofgleks/ui/styles/index.css",
|
|
52
|
+
"src/styles.scss", // your own styles, after the baseline so they win
|
|
53
|
+
],
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Import components where you use them — every one is standalone:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { Component } from '@angular/core';
|
|
60
|
+
import { ButtonComponent, SelectComponent } from '@guildofgleks/ui';
|
|
61
|
+
|
|
62
|
+
@Component({
|
|
63
|
+
selector: 'app-example',
|
|
64
|
+
imports: [ButtonComponent, SelectComponent],
|
|
65
|
+
template: `
|
|
66
|
+
<gog-select label="Region" [options]="regions" [(value)]="region" />
|
|
67
|
+
<gog-button (gogClick)="save()">Save</gog-button>
|
|
68
|
+
`,
|
|
69
|
+
})
|
|
70
|
+
export class ExampleComponent {}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Core conventions (read once, applies everywhere)
|
|
74
|
+
|
|
75
|
+
These hold for essentially every component in the library. Knowing them means you can guess a
|
|
76
|
+
new component's API correctly instead of guessing wrong and hallucinating an input that doesn't
|
|
77
|
+
exist.
|
|
78
|
+
|
|
79
|
+
- **Selector prefix `gog-`** for components (`gog-button`, `gog-select`, …), attribute selectors
|
|
80
|
+
for directives (`gogTooltip`, `[gogBadge]`).
|
|
81
|
+
- **Outputs are prefixed `gog`** so they never collide with native DOM events —
|
|
82
|
+
`gogClick`, `gogToggle`, `gogSearch`, `gogTabChange`, `gogRemove`, `gogScroll`, `gogLoadMore`,
|
|
83
|
+
`gogDateSelect`. **Inputs keep their natural name** (`variant`, `size`, `disabled`).
|
|
84
|
+
- **Two-way binding via `model()`.** Wherever a component holds a value the consumer drives, it's
|
|
85
|
+
a `model()` input — bind with `[(value)]="signal"` / `[(checked)]="signal"` /
|
|
86
|
+
`[(open)]="signal"` etc., or split into `[value]` + `(valueChange)`.
|
|
87
|
+
- **Every input has a zero-config default.** Nothing requires configuration to render something
|
|
88
|
+
reasonable.
|
|
89
|
+
- **`size` is `GogSize = 'xsm' | 'sm' | 'md' | 'lg' | 'slg'`**, shared by every sized component.
|
|
90
|
+
Default is `'md'` almost everywhere — exceptions: `gog-accordion` and `gog-table` default to
|
|
91
|
+
`'lg'` (their `size` means row/section density, not form-control size), `gog-paginator`
|
|
92
|
+
defaults to `'sm'`.
|
|
93
|
+
- **`variant` is `GogVariant = 'primary' | 'secondary' | 'outline' | 'ghost'`** on `gog-button`.
|
|
94
|
+
Status-colored components (`gog-tag`, `gog-badge`) use a different, four-value
|
|
95
|
+
`GogTagVariant = 'success' | 'danger' | 'warning' | 'info'` instead — don't confuse the two.
|
|
96
|
+
- **`errorDisplay: GogErrorDisplay = 'auto' | 'manual'`** (default `'manual'`) on every control
|
|
97
|
+
that shows a validation message (inputfield, textarea, select, multiselect, autocomplete,
|
|
98
|
+
radio-group, slider, datepicker). `'manual'`: the field shows `errorMessage` whenever it's
|
|
99
|
+
non-empty — you own the timing (`errorMessage="control.invalid && control.touched ? 'Required' : ''"`).
|
|
100
|
+
`'auto'`: shown once the attached `[formControl]`/`formControlName` is touched _and_ invalid —
|
|
101
|
+
you only supply the message text. `'auto'` silently behaves like `'manual'` if there's no real
|
|
102
|
+
form control attached.
|
|
103
|
+
- **`inputId` is optional everywhere.** Every form control renders a real `id` — its own if you
|
|
104
|
+
pass one, a generated one otherwise — so the `<label for>` and the error message's
|
|
105
|
+
`aria-describedby` are always wired up. Pass `inputId` only when something outside the
|
|
106
|
+
component needs to reference the field by a known id; never pass one just to get a label.
|
|
107
|
+
- **User-visible chrome strings come from `GOG_CONFIG.labels`**, not from an input per string —
|
|
108
|
+
"Clear", "Close dialog", "Go to page 4" and the rest. Per-instance label inputs exist where a
|
|
109
|
+
single control realistically differs and win over the config. See
|
|
110
|
+
[`labels`](#labels--translating-the-library).
|
|
111
|
+
- **`floatLabel: GogFloatLabelVariant = 'none' | 'in' | 'on' | 'over'`** (default `'none'`) on
|
|
112
|
+
the six field controls: inputfield, textarea, select, multiselect, autocomplete, datepicker.
|
|
113
|
+
`'in'` floats up but stays inside the border, `'on'` floats to sit centered on the top border
|
|
114
|
+
line, `'over'` floats fully above the field. Pair with `floatLabelShowPlaceholder` (default
|
|
115
|
+
`false`) to reveal the field's own `placeholder` once the label has floated clear.
|
|
116
|
+
- **`clearable`** (default varies) on inputfield, textarea, select, multiselect, autocomplete,
|
|
117
|
+
datepicker — shows a clear (×) button once the field has content. Off by default everywhere
|
|
118
|
+
except `gog-multiselect`, which had one before the input existed.
|
|
119
|
+
- **Generic option accessors, not a fixed DTO.** Any collection-driven control (`gog-select`,
|
|
120
|
+
`gog-multiselect`, `gog-autocomplete`, `gog-button-toggle-group`) takes **your own object
|
|
121
|
+
shape** through `optionLabel` / `optionValue` / `optionDisabled` — each is a property path
|
|
122
|
+
(`'name'`, dot-paths like `'profile.title'` work) **or** a function
|
|
123
|
+
`(option: T) => TResult`. Defaults are `'name'` / `'id'` / `'disabled'`. Set
|
|
124
|
+
`[optionValue]="null"` to emit **the option object itself** instead of a plucked id — the
|
|
125
|
+
control then round-trips your own object with no lookup table needed:
|
|
126
|
+
```html
|
|
127
|
+
<gog-select [options]="members" [optionLabel]="nameOf" [optionValue]="null" [(value)]="member" />
|
|
128
|
+
```
|
|
129
|
+
- **Global defaults via `GOG_CONFIG` / `provideGogConfig(...)`** — see its own section below.
|
|
130
|
+
Precedence is always: the instance's own input (if set) → `GOG_CONFIG` → the component's
|
|
131
|
+
built-in default.
|
|
132
|
+
- **Don't bind both a `model()` and a form directive on the same instance.** Every CVA control
|
|
133
|
+
(checkbox, toggle, radio-group, inputfield, textarea, select, multiselect, autocomplete,
|
|
134
|
+
slider, datepicker) exposes its value as both a two-way `model()` (`[(checked)]`, `[(value)]`)
|
|
135
|
+
and, separately, `ControlValueAccessor` for `[formControl]`/`formControlName`. Pick one per
|
|
136
|
+
instance — wiring both gives the value two competing sources of truth.
|
|
137
|
+
- **The custom-content slot pattern.** Wherever a component needs custom markup for a specific
|
|
138
|
+
part of itself, it's an attribute directive read with `contentChild()`, given a **typed**
|
|
139
|
+
context via `let-` variables — never a plain `TemplateRef` input, never a string-keyed lookup.
|
|
140
|
+
Recognize the shape:
|
|
141
|
+
```html
|
|
142
|
+
<gog-accordion [items]="items">
|
|
143
|
+
<ng-template gogAccordionHeader let-item let-open="open">{{ item.title }}</ng-template>
|
|
144
|
+
</gog-accordion>
|
|
145
|
+
```
|
|
146
|
+
See the per-component tables below for which slot directives exist on which component.
|
|
147
|
+
- **Legacy `TemplateRef` inputs and string-keyed lookups still exist on a few components and
|
|
148
|
+
still work, but are `@deprecated` — do not use them in new code.** See
|
|
149
|
+
[Deprecated patterns — do not use in new code](#deprecated-patterns--do-not-use-in-new-code).
|
|
150
|
+
- **Accessibility is built in**, not optional: keyboard navigation (roving tabindex, arrow keys,
|
|
151
|
+
Home/End), ARIA roles/states, `:focus-visible` styling, `prefers-reduced-motion` handling, and
|
|
152
|
+
WCAG AA contrast are already implemented — you don't need to add any of this yourself, just
|
|
153
|
+
supply `ariaLabel`/`label` inputs where a component has no visible text of its own (icon-only
|
|
154
|
+
buttons, `gog-progressbar`, `gog-scroll`).
|
|
155
|
+
- **`aria-label` on the host tag does nothing.** Several components (`gog-button` chief among
|
|
156
|
+
them) render their real interactive element (a `<button>`) _inside_ the component's own host
|
|
157
|
+
tag. An `aria-label` attribute placed directly on `<gog-button>` in a template lands on the
|
|
158
|
+
custom element wrapper, not on the inner `<button>`, so assistive tech never sees it — always
|
|
159
|
+
use the component's own `ariaLabel` input instead.
|
|
160
|
+
|
|
161
|
+
## Theming
|
|
162
|
+
|
|
163
|
+
Full model is in `README.md`'s Theming section and `theming.md`; short version:
|
|
164
|
+
|
|
165
|
+
- Every visual value (color, spacing, radius, shadow, duration) is a `--gog-*` CSS custom
|
|
166
|
+
property, layered **foundation** (`--gog-accent-color`, `--gog-space-md`, …, restyles
|
|
167
|
+
everything) → **component** (`--gog-btn-primary-bg`, …, one block per component) →
|
|
168
|
+
**instance** (`--gog-btn-bg`, …, deliberately undeclared escape hatch for one element).
|
|
169
|
+
- Theme switch is a `data-theme` attribute, usually on `<html>`, toggled through the
|
|
170
|
+
`ThemeService` (`inject(ThemeService).setTheme('dark')` / `.toggleTheme()` / `.theme` signal).
|
|
171
|
+
Ships `light` and `dark`. Three more importable presets: `slate`, `one-dark`, `one-light`
|
|
172
|
+
(`@guildofgleks/ui/styles/presets/<name>.css`).
|
|
173
|
+
- Restyle one instance without touching a theme: `<gog-button style="--gog-btn-bg: #ff4edb">`.
|
|
174
|
+
- Build a custom theme by declaring a palette against a new `data-theme` value (see
|
|
175
|
+
`theming.md` for the full worked example) — component tokens re-derive automatically, you
|
|
176
|
+
don't restate them.
|
|
177
|
+
|
|
178
|
+
## Global configuration — `GOG_CONFIG` / `provideGogConfig(...)`
|
|
179
|
+
|
|
180
|
+
For the handful of inputs an app typically wants to set once (a size for every form control, a
|
|
181
|
+
locale for every datepicker) rather than repeat on every instance:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
import { provideGogConfig } from '@guildofgleks/ui';
|
|
185
|
+
|
|
186
|
+
bootstrapApplication(App, {
|
|
187
|
+
providers: [
|
|
188
|
+
provideGogConfig({
|
|
189
|
+
control: { size: 'sm', errorDisplay: 'auto', clearable: true },
|
|
190
|
+
dropdown: { appendToBody: true, filter: true },
|
|
191
|
+
datepicker: { locale: 'de-DE', firstDayOfWeek: 1, format: 'dd.MM.yyyy' },
|
|
192
|
+
toast: { position: 'top-right', duration: 4000 },
|
|
193
|
+
}),
|
|
194
|
+
],
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Precedence, always: **instance input → `GOG_CONFIG` → component's built-in default.** A nested
|
|
199
|
+
`provideGogConfig(...)` (in a route's or component's own `providers`) **layers onto the
|
|
200
|
+
parent's config**, one level deep per key — it does not replace it.
|
|
201
|
+
|
|
202
|
+
| Key | Fields | Applies to |
|
|
203
|
+
| -------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
204
|
+
| `control` | `size`, `errorDisplay`, `clearable` | `size`: button, inputfield, textarea, select, multiselect, checkbox, radio-group, button-toggle-group, datepicker. `errorDisplay`: inputfield, textarea, select, multiselect, autocomplete, radio-group, slider, datepicker. `clearable`: inputfield, textarea, select, multiselect, autocomplete, datepicker. Not table/accordion/paginator (density, not form size), not spinner/skeleton/tag/chip/toggle. |
|
|
205
|
+
| `dropdown` | `appendToBody`, `direction`, `filter`, `filterPosition` | `gog-select`, `gog-multiselect`. `gog-datepicker`/`gog-autocomplete` honour `appendToBody`/`direction` too (autocomplete has no `filter` box — it filters via the trigger's own text). |
|
|
206
|
+
| `floatLabel` | `variant`, `showPlaceholder` | inputfield, textarea, select, multiselect, autocomplete, datepicker. |
|
|
207
|
+
| `datepicker` | `locale`, `firstDayOfWeek`, `format` | `gog-datepicker`, `gog-calendar`. |
|
|
208
|
+
| `autocomplete` | `searchDebounce`, `minLength`, `openOnFocus` | `gog-autocomplete`. |
|
|
209
|
+
| `tooltip` | `position`, `showDelay`, `hideDelay` | the `gogTooltip` directive. |
|
|
210
|
+
| `scroll` | `autoHide`, `hideDelay`, `size`, `overscrollBehavior`, `showTrack` | `gog-scroll` (and every component that uses one internally). |
|
|
211
|
+
| `button` | `debounce` | `gog-button`. |
|
|
212
|
+
| `inputfield` | `showSpinButtons` | `gog-inputfield`. |
|
|
213
|
+
| `textarea` | `resize` | `gog-textarea`. |
|
|
214
|
+
| `paginator` | `showPageSizeSelect`, `pageSizeOptions` | `gog-paginator`, and through it `gog-table`'s built-in pagination.
|
|
215
|
+
| `toast` | `position`, `duration` | `ToastService`. |
|
|
216
|
+
| `theme` | `storageKey`, `defaultTheme`, `followSystem`, `lightTheme`, `darkTheme` | `ThemeService`. All off/neutral by default — see below. |
|
|
217
|
+
| `labels` | every fixed string the library renders — see below | inputfield, textarea, select, multiselect, autocomplete, datepicker, calendar, paginator, table, `DialogService`, `ToastService`. |
|
|
218
|
+
|
|
219
|
+
Anything visual does **not** belong here — override the `--gog-*` token instead.
|
|
220
|
+
|
|
221
|
+
### `labels` — translating the library
|
|
222
|
+
|
|
223
|
+
Every string a component renders that the consumer never writes markup for. An app that isn't
|
|
224
|
+
in English sets these once rather than on every control:
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
provideGogConfig({
|
|
228
|
+
labels: {
|
|
229
|
+
clear: 'Очистить', // inputfield / textarea clear button
|
|
230
|
+
clearSelection: 'Очистить выбор', // select / multiselect / autocomplete
|
|
231
|
+
clearDate: 'Очистить дату', // datepicker
|
|
232
|
+
selectAll: 'Выбрать все', // multiselect panel
|
|
233
|
+
clearAll: 'Очистить', // multiselect panel
|
|
234
|
+
increment: 'Увеличить', // number spin buttons
|
|
235
|
+
decrement: 'Уменьшить',
|
|
236
|
+
showPassword: 'Показать пароль',
|
|
237
|
+
hidePassword: 'Скрыть пароль',
|
|
238
|
+
closeDialog: 'Закрыть',
|
|
239
|
+
closeToast: 'Закрыть',
|
|
240
|
+
pagination: 'Навигация по страницам',
|
|
241
|
+
previousPage: 'Предыдущая страница',
|
|
242
|
+
nextPage: 'Следующая страница',
|
|
243
|
+
openCalendar: 'Открыть календарь',
|
|
244
|
+
rowsPerPage: 'Строк на странице', // gog-paginator's size select
|
|
245
|
+
total: 'Всего', // gog-table's row-count label
|
|
246
|
+
tablePagination: 'Навигация по таблице',
|
|
247
|
+
selectRow: 'Выбрать строку',
|
|
248
|
+
selectAllRows: 'Выбрать все строки на странице',
|
|
249
|
+
today: 'Сегодня',
|
|
250
|
+
thisMonth: 'Текущий месяц',
|
|
251
|
+
previousMonth: 'Предыдущий месяц',
|
|
252
|
+
nextMonth: 'Следующий месяц',
|
|
253
|
+
previousYear: 'Предыдущий год',
|
|
254
|
+
nextYear: 'Следующий год',
|
|
255
|
+
hours: 'Часы',
|
|
256
|
+
minutes: 'Минуты',
|
|
257
|
+
seconds: 'Секунды',
|
|
258
|
+
// The one non-string field: it interpolates the page number, and word order and
|
|
259
|
+
// agreement around a number vary by language, so it takes a formatter.
|
|
260
|
+
page: (page, isCurrent) =>
|
|
261
|
+
isCurrent ? `Страница ${page}, текущая` : `Перейти на страницу ${page}`,
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Strings that describe **one** control rather than library chrome — `gog-checkbox`'s `ariaLabel`,
|
|
267
|
+
`gog-button`'s `ariaLabel`, any field's `label`/`placeholder` — are deliberately **not** here.
|
|
268
|
+
Those stay per instance. Where a per-instance label input exists (`clearAriaLabel`, `todayLabel`,
|
|
269
|
+
…) it still wins over the configured value.
|
|
270
|
+
|
|
271
|
+
## Services
|
|
272
|
+
|
|
273
|
+
### `ThemeService`
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
private readonly theme = inject(ThemeService);
|
|
277
|
+
this.theme.theme(); // Signal<string>, READ-ONLY — current data-theme
|
|
278
|
+
this.theme.setTheme('dark'); // any theme name, including a custom one you declared in CSS
|
|
279
|
+
this.theme.toggleTheme(); // flips between the configured light and dark names
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
`theme` is read-only on purpose: writing to it would move the signal without touching the
|
|
283
|
+
`data-theme` attribute the styles actually read. Never suggest `theme.set(...)` — it does not
|
|
284
|
+
exist.
|
|
285
|
+
|
|
286
|
+
Zero-config behaviour: adopt whatever `data-theme` is already on `<html>`, else `'light'`.
|
|
287
|
+
Persistence and following the OS setting are **opt-in**, so upgrading cannot change which theme
|
|
288
|
+
an existing app opens in:
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
provideGogConfig({
|
|
292
|
+
theme: {
|
|
293
|
+
storageKey: 'app-theme', // persist the choice in localStorage; unset = no persistence
|
|
294
|
+
followSystem: true, // open in the OS prefers-color-scheme, and keep following it
|
|
295
|
+
// until the app calls setTheme/toggleTheme
|
|
296
|
+
lightTheme: 'light', // the two names followSystem maps to and toggleTheme alternates
|
|
297
|
+
darkTheme: 'cyberpunk', // between
|
|
298
|
+
defaultTheme: 'light', // used when nothing else decides
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Resolution order at startup: existing `data-theme` on the document → persisted value →
|
|
304
|
+
OS setting (if `followSystem`) → `defaultTheme` → `'light'`.
|
|
305
|
+
|
|
306
|
+
### `ToastService`
|
|
307
|
+
|
|
308
|
+
Root-provided singleton. Requires a `<gog-toast-container />` placed once in your app (see
|
|
309
|
+
[gog-toast](#gog-toast--gog-toast-container) below — it is **not** wired up automatically).
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
private readonly toast = inject(ToastService);
|
|
313
|
+
|
|
314
|
+
this.toast.success('Saved');
|
|
315
|
+
this.toast.error('Could not save', {
|
|
316
|
+
isSticky: true,
|
|
317
|
+
actions: [{ label: 'Retry', onClick: () => this.save() }],
|
|
318
|
+
});
|
|
319
|
+
// also: .warning(msg, config?), .info(msg, config?), .show(config), .dismiss(id), .dismissAll()
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
`ToastConfig`: `{ message, type?, iconName?, iconTemplate?, actions?, dedupeKey?, isSticky?, duration?, position? }`.
|
|
323
|
+
Repeated calls with the same (explicit or inferred) `dedupeKey` replace the existing toast in
|
|
324
|
+
place instead of stacking a duplicate.
|
|
325
|
+
|
|
326
|
+
### `DialogService`
|
|
327
|
+
|
|
328
|
+
Root-provided singleton, imperative dynamic-component dialogs. Requires a `<gog-dialog />`
|
|
329
|
+
placed once in your app (see [gog-dialog](#gog-dialog) below — also **not** automatic).
|
|
330
|
+
|
|
331
|
+
```ts
|
|
332
|
+
private readonly dialogService = inject(DialogService);
|
|
333
|
+
|
|
334
|
+
async confirmDelete(): Promise<void> {
|
|
335
|
+
const handle = this.dialogService.open<boolean>({
|
|
336
|
+
component: ConfirmationDialogComponent, // or your own component
|
|
337
|
+
title: 'Delete this item?',
|
|
338
|
+
role: 'alertdialog',
|
|
339
|
+
data: { message: 'This cannot be undone.' },
|
|
340
|
+
});
|
|
341
|
+
const confirmed = await handle.afterClosed; // boolean | undefined
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
`DialogConfig`: `{ title?, component, data?, modal? (default true), closable?, draggable?, closeIconName?, closeIconTemplate?, width?, maxWidth?, role? ('dialog' default | 'alertdialog'), zIndex? }`.
|
|
346
|
+
`open()` returns `{ close(result?), afterClosed: Promise<TResult | undefined> }`. Also:
|
|
347
|
+
`closeAll(result?)`, `updatePosition(id, offsetX, offsetY)` (for `draggable` dialogs).
|
|
348
|
+
|
|
349
|
+
The library ships a ready-made `ConfirmationDialogComponent` for yes/no prompts — pass it as
|
|
350
|
+
`component` with `data: { title, description, confirmText, cancelText }`; it resolves the
|
|
351
|
+
dialog's result to `true`/`false`.
|
|
352
|
+
|
|
353
|
+
**Wiring a custom component into a dialog** — it reads its data via `DIALOG_DATA` and closes
|
|
354
|
+
itself via `DIALOG_REF`:
|
|
355
|
+
|
|
356
|
+
```ts
|
|
357
|
+
import { Component, inject } from '@angular/core';
|
|
358
|
+
import { DIALOG_DATA, DIALOG_REF } from '@guildofgleks/ui';
|
|
359
|
+
|
|
360
|
+
@Component({ selector: 'app-edit-dialog', template: `…` })
|
|
361
|
+
export class EditDialogComponent {
|
|
362
|
+
protected readonly data = inject<{ userId: string }>(DIALOG_DATA);
|
|
363
|
+
private readonly ref = inject(DIALOG_REF);
|
|
364
|
+
|
|
365
|
+
save(): void {
|
|
366
|
+
this.ref.close({ saved: true });
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Component reference
|
|
374
|
+
|
|
375
|
+
Every component below is exported from `@guildofgleks/ui`'s root — `import { X } from '@guildofgleks/ui'`.
|
|
376
|
+
"CVA" = implements `ControlValueAccessor` (works with `[formControl]`/`formControlName`).
|
|
377
|
+
|
|
378
|
+
### Buttons & choices
|
|
379
|
+
|
|
380
|
+
#### `gog-button`
|
|
381
|
+
|
|
382
|
+
| Input | Type | Default | Notes |
|
|
383
|
+
| ----------- | --------------------------------- | ----------- | ----------------------------------------------------- |
|
|
384
|
+
| `variant` | `GogVariant` | `'primary'` | |
|
|
385
|
+
| `size` | `GogSize \| undefined` | `'md'` | via `GOG_CONFIG.control.size` |
|
|
386
|
+
| `disabled` | `boolean` | `false` | |
|
|
387
|
+
| `fullWidth` | `boolean` | `false` | |
|
|
388
|
+
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | |
|
|
389
|
+
| `loading` | `boolean` | `false` | shows an inline `gog-spinner`, blocks clicks |
|
|
390
|
+
| `debounce` | `number \| undefined` | `300` | ms; via `GOG_CONFIG.button.debounce` — see note below |
|
|
391
|
+
| `ariaLabel` | `string \| null` | `null` | **use this, not a raw `aria-label` attribute** |
|
|
392
|
+
|
|
393
|
+
Outputs: `gogClick: MouseEvent`.
|
|
394
|
+
|
|
395
|
+
**`debounce` is a spam guard, not a delay before the first click.** The first click in a window
|
|
396
|
+
fires immediately (leading edge); further clicks within `debounce` ms are silently dropped.
|
|
397
|
+
|
|
398
|
+
```html
|
|
399
|
+
<gog-button variant="primary" [loading]="saving()" (gogClick)="save()">Save</gog-button>
|
|
400
|
+
<gog-button variant="ghost" ariaLabel="Close" (gogClick)="close()"
|
|
401
|
+
><gog-icon name="close"
|
|
402
|
+
/></gog-button>
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
#### `gog-button-toggle-group`
|
|
406
|
+
|
|
407
|
+
A row of buttons, single- or multi-select, built from your own option objects.
|
|
408
|
+
|
|
409
|
+
| Input | Type | Default | Notes |
|
|
410
|
+
| ------------------------------------ | ------------------------------------------ | ---------------------- | ------------------------------------- |
|
|
411
|
+
| `options` | `TOption[]` | `[]` | |
|
|
412
|
+
| `optionLabel` | accessor | `'name'` | |
|
|
413
|
+
| `optionValue` | accessor \| `null` | `'id'` | `null` emits the option object |
|
|
414
|
+
| `optionDisabled` | accessor | `'disabled'` | |
|
|
415
|
+
| `optionIcon` | accessor → `GogIconName \| null` \| `null` | `null` | optional leading icon per option |
|
|
416
|
+
| `multiple` | `boolean` | `false` | changes ARIA role entirely — see note |
|
|
417
|
+
| `appearance` | `'joined' \| 'separated'` | `'joined'` | |
|
|
418
|
+
| `orientation` | `GogOrientation` | `'horizontal'` | |
|
|
419
|
+
| `size` | `GogSize \| undefined` | `'md'` | via `GOG_CONFIG.control.size` |
|
|
420
|
+
| `disabled`, `fullWidth`, `ariaLabel` | | `false`, `false`, `''` | |
|
|
421
|
+
|
|
422
|
+
Model: `value: TValue | TValue[] | null` (single value, or array in `multiple` mode). CVA: yes.
|
|
423
|
+
Slot: `<ng-template gogButtonToggleOption let-opt let-selected="selected">` for custom button
|
|
424
|
+
markup. **Single mode is a radio group** (`role="radiogroup"`, arrows move _and_ select);
|
|
425
|
+
**multiple mode is a toolbar of independent toggles** (`role="group"`, arrows only move, Space
|
|
426
|
+
toggles) — this is a real ARIA distinction, not cosmetic.
|
|
427
|
+
|
|
428
|
+
```html
|
|
429
|
+
<gog-button-toggle-group [options]="alignments" [(value)]="align" />
|
|
430
|
+
<gog-button-toggle-group [options]="tools" [multiple]="true" [(value)]="activeTools" />
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Form fields
|
|
434
|
+
|
|
435
|
+
#### `gog-inputfield`
|
|
436
|
+
|
|
437
|
+
| Input | Type | Default | Notes |
|
|
438
|
+
| ----------------------------------------- | ------------------------------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------ |
|
|
439
|
+
| `label`, `placeholder` | `string` | `''` | |
|
|
440
|
+
| `type` | `GogInputType` | `'text'` | `text`/`password`/`email`/`number`/`search`/`tel`/`url`/`date`/`time`/`datetime-local` |
|
|
441
|
+
| `readonly` | `boolean` | `false` | value stays focusable and submitted, edits blocked; hides the clear button and stepper |
|
|
442
|
+
| `maxlength`, `minlength` | `number \| null` | `null` | native attributes |
|
|
443
|
+
| `pattern` | `string` | `''` | native attribute, regex source |
|
|
444
|
+
| `inputMode` | `GogInputMode \| null` | `null` | on-screen keyboard hint (`numeric`, `tel`, …) |
|
|
445
|
+
| `spellcheck` | `boolean \| null` | `null` | unset = browser default |
|
|
446
|
+
| `inputId` | `string` | `''` → generated | a real id is always rendered; pass one only to reference the field externally |
|
|
447
|
+
| `min`, `max`, `step` | `number \| null` | `null` | `type="number"` only |
|
|
448
|
+
| `showSpinButtons` | `boolean \| undefined` | `true` | own +/- glyphs on `type="number"`; via `GOG_CONFIG.inputfield.showSpinButtons` |
|
|
449
|
+
| `errorMessage`, `errorDisplay` | | `''`, `'manual'` | see conventions |
|
|
450
|
+
| `disabled`, `size`, `fullWidth` | | `false`, `'md'`, `true` | |
|
|
451
|
+
| `iconStart` / `iconEnd` | `GogIconName \| ''` | `''` | bare leading/trailing icon |
|
|
452
|
+
| `clearable`, `clearAriaLabel` | | `false`, `'Clear'` | on `type="number"` the clear button renders alongside the stepper |
|
|
453
|
+
| `floatLabel`, `floatLabelShowPlaceholder` | | `'none'`, `false` | |
|
|
454
|
+
| `showPasswordLabel` / `hidePasswordLabel` | `string \| undefined` | `'Show password'`/`'Hide password'` | `type="password"` reveal toggle aria-labels; via `GOG_CONFIG.labels` |
|
|
455
|
+
| `incrementLabel` / `decrementLabel` | `string \| undefined` | `'Increment'`/`'Decrement'` | spin button aria-labels; via `GOG_CONFIG.labels` |
|
|
456
|
+
|
|
457
|
+
Model: `value: string` (always a string, even for `type="number"` — the _form control_ value is
|
|
458
|
+
`number | null`, but the `[(value)]` model mirrors the raw text). CVA: yes.
|
|
459
|
+
|
|
460
|
+
Slots: project `<span gogInputAddonStart>`/`<span gogInputAddonEnd>` (or a `<button>`) for
|
|
461
|
+
custom leading/trailing markup — a normal DOM element with its own `aria-label`, click handler
|
|
462
|
+
and disabled state, not a component-managed slot. This is the **current, non-deprecated**
|
|
463
|
+
replacement for the old icon-template/icon-fn/icon-label input quartet — see
|
|
464
|
+
[Deprecated patterns](#deprecated-patterns--do-not-use-in-new-code).
|
|
465
|
+
|
|
466
|
+
```html
|
|
467
|
+
<gog-inputfield
|
|
468
|
+
label="Email"
|
|
469
|
+
type="email"
|
|
470
|
+
formControlName="email"
|
|
471
|
+
errorDisplay="auto"
|
|
472
|
+
errorMessage="Enter a valid email"
|
|
473
|
+
[clearable]="true"
|
|
474
|
+
/>
|
|
475
|
+
|
|
476
|
+
<gog-inputfield label="Amount" [fullWidth]="false">
|
|
477
|
+
<span gogInputAddonStart>€</span>
|
|
478
|
+
</gog-inputfield>
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
#### `gog-textarea`
|
|
482
|
+
|
|
483
|
+
| Input | Type | Default |
|
|
484
|
+
| ------------------------------------------------------------------------ | ----------------------------------------------------------------------------- | ---------------------------------------------- |
|
|
485
|
+
| `label`, `placeholder` | `string` | `''` |
|
|
486
|
+
| `rows` | `number` | `4` |
|
|
487
|
+
| `readonly` | `boolean` | `false` |
|
|
488
|
+
| `maxlength`, `minlength` | `number \| null` | `null` |
|
|
489
|
+
| `spellcheck` | `boolean \| null` | `null` |
|
|
490
|
+
| `inputId` | `string` | `''` → generated, same as inputfield |
|
|
491
|
+
| `resize` | `GogTextareaResize \| undefined` (`'vertical'\|'horizontal'\|'both'\|'none'`) | `'vertical'`; via `GOG_CONFIG.textarea.resize` |
|
|
492
|
+
| `errorMessage`, `errorDisplay`, `disabled`, `size`, `fullWidth` | | same shape as inputfield |
|
|
493
|
+
| `clearable`, `clearAriaLabel`, `floatLabel`, `floatLabelShowPlaceholder` | | same shape as inputfield |
|
|
494
|
+
|
|
495
|
+
Model: `value: string`. CVA: yes.
|
|
496
|
+
|
|
497
|
+
```html
|
|
498
|
+
<gog-textarea label="Notes" formControlName="notes" [rows]="6" resize="vertical" />
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### `gog-select`
|
|
502
|
+
|
|
503
|
+
Extends the shared listbox behaviour (`GogDropdownBase`) that also backs `gog-multiselect` and
|
|
504
|
+
partly `gog-autocomplete` — placement, the append-to-body overlay, click-outside, keyboard nav,
|
|
505
|
+
and CVA all come from there. Full shared input surface (documented once, applies to both select
|
|
506
|
+
and multiselect unless noted otherwise):
|
|
507
|
+
|
|
508
|
+
| Input | Type | Default | Notes |
|
|
509
|
+
| ------------------------------------------------------ | --------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
|
|
510
|
+
| `label`, `ariaLabel`, `placeholder` | `string` | `''`, `''`, `'Select...'` | |
|
|
511
|
+
| `options` | `TOption[]` | `[]` | your own objects |
|
|
512
|
+
| `optionLabel` | accessor | `'name'` | path or fn |
|
|
513
|
+
| `optionValue` | accessor \| `null` | `'id'` | `null` = emit the option object |
|
|
514
|
+
| `optionDisabled` | accessor | `'disabled'` | |
|
|
515
|
+
| `clearable`, `clearAriaLabel` | | `false` (select) / `true` (multiselect), `'Clear selection'` | |
|
|
516
|
+
| `minWidth` | `string \| null` | `null` | only with `[fullWidth]="false"` |
|
|
517
|
+
| `filter` | `boolean \| undefined` | `false` | search box in the panel; via `GOG_CONFIG.dropdown.filter` |
|
|
518
|
+
| `filterPlaceholder`, `filterEmptyMessage` | `string` | `'Search...'`, `'No matches'` | |
|
|
519
|
+
| `filterPosition` | `'top' \| 'bottom' \| undefined` | `'top'` | via `GOG_CONFIG.dropdown.filterPosition` |
|
|
520
|
+
| `filterMatch` | `((option, query) => boolean) \| null` | `null` | custom matcher, else case-insensitive substring on the resolved label |
|
|
521
|
+
| `errorMessage`, `errorDisplay` | | `''`, `'manual'` | |
|
|
522
|
+
| `size` | `GogSize \| undefined` | `'md'` | |
|
|
523
|
+
| `dropdownDirection` | `'auto' \| 'up' \| 'down' \| undefined` | `'auto'` | |
|
|
524
|
+
| `dropdownZIndex`, `dropdownWidth`, `dropdownMaxHeight` | | `null` | only meaningful with `appendToBody` |
|
|
525
|
+
| `appendToBody` | `boolean \| undefined` | `false` | renders the panel into `<body>` — needed inside a scroll/overflow-clipped container |
|
|
526
|
+
| `disabled`, `fullWidth` | | `false`, `true` | |
|
|
527
|
+
| `floatLabel`, `floatLabelShowPlaceholder` | | `'none'`, `false` | |
|
|
528
|
+
| `inputId` (select/autocomplete only) | `string` | `''` | |
|
|
529
|
+
|
|
530
|
+
`gog-select`-specific: `value: model<TValue>(null)`.
|
|
531
|
+
`gog-multiselect`-specific additions: `value: model<TValue[]>([])`, `showControls: boolean` (default `false`, a select-all/clear row), `controlsPosition: 'top'|'bottom'` (default `'top'`), and `selectAllLabel`/`clearAllLabel` for that row's two buttons (`'Select all'`/`'Clear'`, also via `GOG_CONFIG.labels`).
|
|
532
|
+
|
|
533
|
+
CVA: yes, both. Slots (shared): `<ng-template gogDropdownChevron>` (custom chevron markup),
|
|
534
|
+
`<ng-template gogDropdownOption let-opt let-selected="selected" let-label="label">` (custom
|
|
535
|
+
option row). Multiselect adds `<ng-template gogMultiselectClearIcon>`.
|
|
536
|
+
|
|
537
|
+
```html
|
|
538
|
+
<gog-select
|
|
539
|
+
label="Region"
|
|
540
|
+
[options]="regions"
|
|
541
|
+
optionLabel="title"
|
|
542
|
+
[(value)]="regionId"
|
|
543
|
+
[filter]="true"
|
|
544
|
+
/>
|
|
545
|
+
|
|
546
|
+
<gog-multiselect
|
|
547
|
+
label="Tags"
|
|
548
|
+
[options]="tags"
|
|
549
|
+
[(value)]="selectedTagIds"
|
|
550
|
+
[showControls]="true"
|
|
551
|
+
formControlName="tags"
|
|
552
|
+
errorDisplay="auto"
|
|
553
|
+
/>
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
#### `gog-autocomplete`
|
|
557
|
+
|
|
558
|
+
Shares `GogDropdownBase` too, but the trigger is a real `<input>` (combobox pattern,
|
|
559
|
+
`aria-activedescendant`), not a listbox button — so it does **not** reuse the base's built-in
|
|
560
|
+
panel-filter box; it filters/searches off what's typed in the field itself.
|
|
561
|
+
|
|
562
|
+
| Input | Type | Default | Notes |
|
|
563
|
+
| ------------------------------------------------------------------------------------------------------ | ---------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
564
|
+
| _(all the shared `GogDropdownBase` inputs above except `filter`/`filterPlaceholder`/`filterPosition`)_ | | | |
|
|
565
|
+
| `filterLocal` | `boolean` | `true` | narrow `options` client-side as you type; turn **off** when `gogSearch` already returns a filtered server list (avoids double-filtering) |
|
|
566
|
+
| `minLength` | `number \| undefined` | `1` | via `GOG_CONFIG.autocomplete.minLength` |
|
|
567
|
+
| `openOnFocus` | `boolean \| undefined` | `true` | via `GOG_CONFIG.autocomplete.openOnFocus` |
|
|
568
|
+
| `searchDebounce` | `number \| undefined` | `300` | ms before `gogSearch` fires; via `GOG_CONFIG.autocomplete.searchDebounce` |
|
|
569
|
+
| `loading` | `boolean` | `false` | shows a spinner in the trailing slot |
|
|
570
|
+
| `emptyMessage` | `string` | `'No matches'` | |
|
|
571
|
+
| `forceSelection` | `boolean` | `true` | see note below |
|
|
572
|
+
|
|
573
|
+
Outputs: `gogSearch: string` (debounced query — wire your server lookup here),
|
|
574
|
+
`gogLoadMore: void` (panel scrolled to the end — fetch the next page).
|
|
575
|
+
|
|
576
|
+
Model: `value: TValue | null`. CVA: yes.
|
|
577
|
+
|
|
578
|
+
**`forceSelection` matters.** On (default): the field always ends up reflecting a real
|
|
579
|
+
selection — free-typed text that matches nothing snaps back on blur/Escape. Off: what the user
|
|
580
|
+
typed is itself meaningful (a create-as-you-type flow) — read the typed text from `gogSearch`,
|
|
581
|
+
not from `value`, since `value` clears the moment the text stops matching the selection.
|
|
582
|
+
|
|
583
|
+
```html
|
|
584
|
+
<gog-autocomplete
|
|
585
|
+
[options]="users"
|
|
586
|
+
optionLabel="profile.fullName"
|
|
587
|
+
[optionValue]="null"
|
|
588
|
+
[(value)]="user"
|
|
589
|
+
[loading]="searching()"
|
|
590
|
+
(gogSearch)="search($event)"
|
|
591
|
+
/>
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
#### `gog-checkbox`
|
|
595
|
+
|
|
596
|
+
| Input | Type | Default |
|
|
597
|
+
| ---------------------------------------- | ---------------------- | ------- |
|
|
598
|
+
| `label`, `ariaLabel` | `string` | `''` |
|
|
599
|
+
| `size` | `GogSize \| undefined` | `'md'` |
|
|
600
|
+
| `indeterminate`, `disabled`, `fullWidth` | `boolean` | `false` |
|
|
601
|
+
|
|
602
|
+
Model: `checked: boolean`. CVA: yes. Slot: `<ng-template gogCheckboxIcon>` for a custom tick
|
|
603
|
+
icon (replaces the deprecated `checkIconTemplate` input).
|
|
604
|
+
|
|
605
|
+
```html
|
|
606
|
+
<gog-checkbox label="I agree to the terms" formControlName="agree" />
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
#### `gog-toggle`
|
|
610
|
+
|
|
611
|
+
An on/off switch (`role="switch"`) — semantically different from a checkbox ("is this setting
|
|
612
|
+
on", not "is this one of the things you selected").
|
|
613
|
+
|
|
614
|
+
| Input | Type | Default |
|
|
615
|
+
| ----------------------- | ---------------------- | ------- |
|
|
616
|
+
| `label`, `ariaLabel` | `string` | `''` |
|
|
617
|
+
| `size` | `GogSize \| undefined` | `'md'` |
|
|
618
|
+
| `disabled`, `fullWidth` | `boolean` | `false` |
|
|
619
|
+
| `labelPosition` | `'start' \| 'end'` | `'end'` |
|
|
620
|
+
| `onLabel`, `offLabel` | `string` | `''` | text rendered inside the track itself |
|
|
621
|
+
|
|
622
|
+
Model: `checked: boolean`. CVA: yes.
|
|
623
|
+
|
|
624
|
+
```html
|
|
625
|
+
<gog-toggle label="Notifications" formControlName="notificationsOn" onLabel="ON" offLabel="OFF" />
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
#### `gog-radio-group`
|
|
629
|
+
|
|
630
|
+
| Input | Type | Default |
|
|
631
|
+
| ------------------------------ | ----------------------------------------------- | ---------------- |
|
|
632
|
+
| `options` | `GogRadioOption[]` (`{ id, label, disabled? }`) | `[]` |
|
|
633
|
+
| `label`, `ariaLabel`, `name` | `string` | `''` |
|
|
634
|
+
| `size` | `GogSize \| undefined` | `'md'` |
|
|
635
|
+
| `disabled`, `fullWidth` | `boolean` | `false` |
|
|
636
|
+
| `orientation` | `GogOrientation` | `'vertical'` |
|
|
637
|
+
| `errorMessage`, `errorDisplay` | | `''`, `'manual'` |
|
|
638
|
+
|
|
639
|
+
Model: `value: string | number | null`. CVA: yes. Fixed `{ id, label, disabled? }` shape (not
|
|
640
|
+
a generic accessor, unlike select/multiselect/button-toggle).
|
|
641
|
+
|
|
642
|
+
```html
|
|
643
|
+
<gog-radio-group
|
|
644
|
+
[options]="[{id:'m',label:'Male'},{id:'f',label:'Female'}]"
|
|
645
|
+
formControlName="gender"
|
|
646
|
+
/>
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
#### `gog-slider`
|
|
650
|
+
|
|
651
|
+
| Input | Type | Default |
|
|
652
|
+
| ------------------------------ | ---------------------- | ---------------------------------------------- |
|
|
653
|
+
| `label`, `ariaLabel` | `string` | `''` |
|
|
654
|
+
| `min`, `max`, `step` | `number` | `0`, `100`, `1` |
|
|
655
|
+
| `showValue`, `showThumb` | `boolean` | `true` |
|
|
656
|
+
| `errorMessage`, `errorDisplay` | | `''`, `'manual'` |
|
|
657
|
+
| `disabled` | `boolean` | `false` |
|
|
658
|
+
| `fullWidth` | `boolean` | `true` (ignored when `orientation="vertical"`) |
|
|
659
|
+
| `orientation` | `GogSliderOrientation` | `'horizontal'` |
|
|
660
|
+
|
|
661
|
+
Model: `value: number`. CVA: yes. Backed by a real `<input type="range">` (rotated via
|
|
662
|
+
`writing-mode` for vertical), so dragging/touch/keyboard all come from the platform.
|
|
663
|
+
|
|
664
|
+
```html
|
|
665
|
+
<gog-slider label="Volume" [min]="0" [max]="100" formControlName="volume" />
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
#### `gog-datepicker` / `gog-calendar`
|
|
669
|
+
|
|
670
|
+
`gog-datepicker` is a field + panel; `gog-calendar` is the month grid alone (what `inline` mode
|
|
671
|
+
renders). Native `Date` only — no date library, no adapter.
|
|
672
|
+
|
|
673
|
+
| Input | Type | Default | Notes |
|
|
674
|
+
| ----------------------------------------------------- | -------------------------------------------- | ----------------------------- | ---------------------------------------------------------------------------- |
|
|
675
|
+
| `inputId`, `label`, `ariaLabel`, `placeholder` | `string` | `''` | |
|
|
676
|
+
| `selectionMode` | `GogDateSelectionMode` (`'single'\|'range'`) | `'single'` | |
|
|
677
|
+
| `min`, `max` | `Date \| null` | `null` | |
|
|
678
|
+
| `disabledDates` | `((date: Date) => boolean) \| null` | `null` | predicate, not a list |
|
|
679
|
+
| `defaultMonth` | `Date \| null` | `null` | which month opens when nothing is selected |
|
|
680
|
+
| `numberOfMonths` | `number` | `1` | `2` is what makes a range picker usable |
|
|
681
|
+
| `showTime`, `hourFormat`, `minuteStep`, `showSeconds` | | `false`, `'24'`, `1`, `false` | |
|
|
682
|
+
| `showTodayButton` | `boolean` | `true` | **selects** today |
|
|
683
|
+
| `showThisMonthButton` | `boolean` | `false` | only moves the _view_, leaves selection alone |
|
|
684
|
+
| `format` | `string \| null` | `null` | display/parse pattern (`'dd.MM.yyyy'`); derived from `showTime` when unset |
|
|
685
|
+
| `locale` | `string \| undefined` | `'en-US'` | via `GOG_CONFIG.datepicker.locale` |
|
|
686
|
+
| `firstDayOfWeek` | `number \| undefined` | locale's own | via `GOG_CONFIG.datepicker.firstDayOfWeek` |
|
|
687
|
+
| `allowTextInput` | `boolean` | `true` | typed text parsed against `format`; unparseable drafts don't clear the value |
|
|
688
|
+
| `inline` | `boolean` | `false` | renders the calendar with no field/panel |
|
|
689
|
+
| `disabled`, `fullWidth` | | `false`, `true` | |
|
|
690
|
+
| `clearable`, `clearAriaLabel` | | `false`, `'Clear date'` | |
|
|
691
|
+
| `errorMessage`, `errorDisplay`, `size` | | `''`, `'manual'`, `'md'` | |
|
|
692
|
+
| `floatLabel`, `floatLabelShowPlaceholder` | | `'none'`, `false` | |
|
|
693
|
+
| `appendToBody`, `dropdownDirection`, `dropdownZIndex` | | `false`, `'auto'`, `null` | |
|
|
694
|
+
|
|
695
|
+
Model: `value: Date | GogDateRange | null` (`GogDateRange = { start: Date | null; end: Date | null }`).
|
|
696
|
+
CVA: yes.
|
|
697
|
+
|
|
698
|
+
`gog-calendar` (usable standalone) takes most of the same date/range/time inputs directly, plus
|
|
699
|
+
`gogDateSelect: output<GogDatepickerValue>()` fired only on a _complete_ selection. It resolves
|
|
700
|
+
`locale` and `firstDayOfWeek` from `GOG_CONFIG.datepicker` itself, so a standalone calendar
|
|
701
|
+
honours an app-wide locale without being handed one; its navigation, shortcut and time labels
|
|
702
|
+
(`todayLabel`, `thisMonthLabel`, `previousMonthLabel`, `nextMonthLabel`, `previousYearLabel`,
|
|
703
|
+
`nextYearLabel`, `hoursLabel`, `minutesLabel`, `secondsLabel`) resolve through
|
|
704
|
+
`GOG_CONFIG.labels` the same way.
|
|
705
|
+
|
|
706
|
+
Also exported for direct reuse: `formatDate(date, pattern)`, `parseDate(text, pattern)`, and a
|
|
707
|
+
family of date-math helpers (`addDays`, `addMonths`, `isSameDay`, `isWithinBounds`, …) from
|
|
708
|
+
`date-utils`.
|
|
709
|
+
|
|
710
|
+
```html
|
|
711
|
+
<gog-datepicker label="Birth date" [(value)]="birthDate" [max]="today" />
|
|
712
|
+
<gog-datepicker selectionMode="range" [(value)]="stayRange" [numberOfMonths]="2" />
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
### Display, feedback & status
|
|
716
|
+
|
|
717
|
+
#### `gog-icon`
|
|
718
|
+
|
|
719
|
+
| Input | Type | Default |
|
|
720
|
+
| ------------ | --------------------- | -------------------------------------------------- |
|
|
721
|
+
| `name` | `GogIconName` | `'close'` |
|
|
722
|
+
| `template` | `TemplateRef \| null` | `null` — custom markup instead of the built-in SVG |
|
|
723
|
+
| `title` | `string` | `''` |
|
|
724
|
+
| `ariaHidden` | `boolean` | `true` |
|
|
725
|
+
|
|
726
|
+
The package ships **41** glyphs (`GogBuiltinIconName`), all from [Lucide](https://lucide.dev)
|
|
727
|
+
and inlined so the package keeps zero runtime dependencies:
|
|
728
|
+
|
|
729
|
+
| Group | Names |
|
|
730
|
+
| --- | --- |
|
|
731
|
+
| Chevrons & arrows | `chevron-up`, `chevron-down`, `chevron-left`, `chevron-right`, `arrow-left`, `arrow-right` |
|
|
732
|
+
| Confirm & dismiss | `check`, `close`, `checkbox`, `checkbox-checked` |
|
|
733
|
+
| Status | `success`, `error`, `warning`, `info` |
|
|
734
|
+
| Sorting | `sort`, `sort-up`, `sort-down`, `filter` |
|
|
735
|
+
| Actions | `search`, `plus`, `minus`, `trash`, `pencil`, `copy`, `download`, `upload`, `refresh`, `external-link` |
|
|
736
|
+
| Chrome | `menu`, `more-horizontal`, `more-vertical`, `settings` |
|
|
737
|
+
| Objects & state | `user`, `lock`, `mail`, `calendar`, `clock`, `eye`, `eye-off`, `star`, `star-filled` |
|
|
738
|
+
|
|
739
|
+
`star` / `star-filled` is the one outline/filled pair, for a rating or favourite **toggle** —
|
|
740
|
+
the same reason `checkbox` / `checkbox-checked` exists. The set is otherwise outline-only on
|
|
741
|
+
purpose; a blanket solid duplicate of every glyph would double the payload for a distinction
|
|
742
|
+
almost nothing needs. If you want a filled variant of something else, register it with
|
|
743
|
+
`provideGogIcons`.
|
|
744
|
+
|
|
745
|
+
`Object.keys(ICON_DEFS)` is the runtime list, if you need to enumerate them (an icon picker, a
|
|
746
|
+
gallery). Do not hand-copy the names into an array — that is what goes stale.
|
|
747
|
+
|
|
748
|
+
```html
|
|
749
|
+
<gog-icon name="calendar" />
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
##### Registering your own icons — `provideGogIcons(...)`
|
|
753
|
+
|
|
754
|
+
`name` is typed `GogIconName = GogBuiltinIconName | (string & {})`: the built-ins autocomplete,
|
|
755
|
+
and any name you register is accepted. **This is the supported way to use your own icon set** —
|
|
756
|
+
prefer it over the `template` input, which costs an `<ng-template>` at every use site and is for
|
|
757
|
+
one-offs.
|
|
758
|
+
|
|
759
|
+
```ts
|
|
760
|
+
// app.config.ts
|
|
761
|
+
import { provideGogIcons } from '@guildofgleks/ui';
|
|
762
|
+
|
|
763
|
+
providers: [
|
|
764
|
+
provideGogIcons({
|
|
765
|
+
cart: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">…</svg>',
|
|
766
|
+
rocket: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">…</svg>',
|
|
767
|
+
}),
|
|
768
|
+
];
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
```html
|
|
772
|
+
<gog-icon name="cart" />
|
|
773
|
+
<gog-tag iconName="cart">In basket</gog-tag>
|
|
774
|
+
<!-- works anywhere an icon *name* is taken -->
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
- **Registered names win over built-ins of the same name** — that is how you replace the
|
|
778
|
+
library's checkmark or chevrons across every component at once, without touching any of them.
|
|
779
|
+
- **Nested `provideGogIcons(...)` layers onto the parent set** rather than replacing it, the same
|
|
780
|
+
as `provideGogConfig`: a lazy route can register only what it uses.
|
|
781
|
+
- **An unknown name renders nothing and warns in dev mode; it never throws.** An icon is
|
|
782
|
+
decoration — failing the render over a typo would be the worse outcome.
|
|
783
|
+
- **Write the SVG for inheritance:** a `viewBox`, `stroke="currentColor"` (or `fill`), and no
|
|
784
|
+
width/height — `gog-icon` drives size and stroke width from the `--gog-icon-*` tokens, so a
|
|
785
|
+
registered icon scales and colours like a built-in.
|
|
786
|
+
- **Security:** the markup is inserted with `bypassSecurityTrustHtml` (Angular's HTML sanitizer
|
|
787
|
+
strips SVG, so there is no alternative). That is fine for static icon markup you authored;
|
|
788
|
+
**never** build a registered icon string from user input or fetch it at runtime unsanitized.
|
|
789
|
+
|
|
790
|
+
#### `[gogButton]` — the link-flavoured button
|
|
791
|
+
|
|
792
|
+
`gog-button` renders its own `<button>`, so it can never *be* a link. `[gogButton]` inverts that:
|
|
793
|
+
the element stays yours and the directive only gives it the look.
|
|
794
|
+
|
|
795
|
+
```html
|
|
796
|
+
<a gogButton routerLink="/pricing">See pricing</a>
|
|
797
|
+
<a gogButton variant="ghost" href="https://example.com" target="_blank" rel="noreferrer">Docs</a>
|
|
798
|
+
<button gogButton variant="outline" size="sm" type="submit">Save</button>
|
|
799
|
+
<a gogButton fullWidth routerLink="/checkout">Checkout</a>
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
| Input | Type | Default |
|
|
803
|
+
| ----------- | ----------------------- | ------------------------------------ |
|
|
804
|
+
| `variant` | `GogVariant` | `'primary'` |
|
|
805
|
+
| `size` | `GogSize \| undefined` | `'md'`; via `GOG_CONFIG.control.size` |
|
|
806
|
+
| `fullWidth` | `boolean` (bare attr ok) | `false` |
|
|
807
|
+
|
|
808
|
+
Selector is `a[gogButton], button[gogButton]` — deliberately not a bare `[gogButton]`, because on
|
|
809
|
+
a `<div>` the result looks like a button and is invisible to the keyboard and to assistive tech.
|
|
810
|
+
|
|
811
|
+
**Which to reach for.** `gog-button` for a button that acts on the page: it owns `loading` (a
|
|
812
|
+
centred spinner it projects), `debounce` click throttling and the `gogClick` output, none of which
|
|
813
|
+
a bare element can provide. `[gogButton]` when the element must be a link, or when you need to
|
|
814
|
+
keep directives of your own on it — `routerLink`, `href`, `target`, `download`, `type="submit"`
|
|
815
|
+
and anything else keep working because they were never brokered through an input in the first
|
|
816
|
+
place. That is also why the library still has no `@angular/router` dependency.
|
|
817
|
+
|
|
818
|
+
Two things it deliberately does not do: no `disabled` on an `<a>` (there is no such thing — drop
|
|
819
|
+
the `href` or render a real `<button>`), and no loading state (the spinner is a projected child a
|
|
820
|
+
directive cannot add without taking over the element's content).
|
|
821
|
+
|
|
822
|
+
#### `[gogBadge]` — directive, not a component
|
|
823
|
+
|
|
824
|
+
Decorates an existing element (a button, an icon, an avatar) with a count/status dot — it never
|
|
825
|
+
wraps its host.
|
|
826
|
+
|
|
827
|
+
| Input | Type | Default |
|
|
828
|
+
| ---------------- | --------------------------------------------------------------------------- | -------------------------------- |
|
|
829
|
+
| `gogBadge` | `string \| number \| null` | `null` — the content |
|
|
830
|
+
| `badgePosition` | `GogBadgePosition` (`'top-end'\|'top-start'\|'bottom-end'\|'bottom-start'`) | `'top-end'` |
|
|
831
|
+
| `badgeVariant` | `GogTagVariant` | `'danger'` |
|
|
832
|
+
| `badgeDot` | `boolean` | `false` — bare dot, no text |
|
|
833
|
+
| `badgeMax` | `number` | `99` — beyond this, renders `N+` |
|
|
834
|
+
| `badgeHidden` | `boolean` | `false` |
|
|
835
|
+
| `badgeAriaLabel` | `string` | `''` |
|
|
836
|
+
|
|
837
|
+
Renders **nothing** when the value is `0`, `null` or empty and `badgeDot` is off — "0" badges
|
|
838
|
+
are impossible by design.
|
|
839
|
+
|
|
840
|
+
```html
|
|
841
|
+
<gog-button gogBadge="12" badgeAriaLabel="12 unread">Inbox</gog-button>
|
|
842
|
+
<gog-icon name="info" gogBadge badgeDot />
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
#### `gog-chip`
|
|
846
|
+
|
|
847
|
+
| Input | Type | Default |
|
|
848
|
+
| ------------------------------ | ----------------------------------- | --------------------- |
|
|
849
|
+
| `size` | `GogSize` | `'md'` |
|
|
850
|
+
| `shape` | `GogTagShape` (`'rounded'\|'pill'`) | `'rounded'` |
|
|
851
|
+
| `disabled`, `clickable` | `boolean` | `false`, `true` |
|
|
852
|
+
| `removable` | `boolean` | `false` |
|
|
853
|
+
| `fullWidth` | `boolean` | `false` |
|
|
854
|
+
| `ariaLabel`, `removeAriaLabel` | `string` | `''`, `'Remove chip'` |
|
|
855
|
+
| `avatarUrl`, `avatarAlt` | `string \| null` / `string` | `null`, `''` |
|
|
856
|
+
| `iconName` | `GogIconName \| null` | `null` |
|
|
857
|
+
|
|
858
|
+
Outputs: `gogClick: MouseEvent | KeyboardEvent`, `gogRemove: void`.
|
|
859
|
+
|
|
860
|
+
```html
|
|
861
|
+
<gog-chip [avatarUrl]="user.photo" [removable]="true" (gogRemove)="removeUser(user)"
|
|
862
|
+
>{{ user.name }}</gog-chip
|
|
863
|
+
>
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
#### `gog-tag`
|
|
867
|
+
|
|
868
|
+
| Input | Type | Default |
|
|
869
|
+
| ----------- | --------------------- | ----------- |
|
|
870
|
+
| `variant` | `GogTagVariant` | `'info'` |
|
|
871
|
+
| `size` | `GogSize` | `'md'` |
|
|
872
|
+
| `shape` | `GogTagShape` | `'rounded'` |
|
|
873
|
+
| `iconName` | `GogIconName \| null` | `null` |
|
|
874
|
+
| `fullWidth` | `boolean` | `false` |
|
|
875
|
+
|
|
876
|
+
Slot: `<ng-template gogTagIcon>` for custom icon markup (replaces the deprecated `iconTemplate`).
|
|
877
|
+
|
|
878
|
+
```html
|
|
879
|
+
<gog-tag variant="success">Active</gog-tag>
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
#### `gog-spinner` / `gog-spinner-overlay`
|
|
883
|
+
|
|
884
|
+
| Input | Type | Default |
|
|
885
|
+
| -------------------------------- | ------------------------------------------------- | ------------------------------------------- |
|
|
886
|
+
| `size` | `GogSize` | `'md'` |
|
|
887
|
+
| `variant` | `GogSpinnerVariant` (`'runic'\|'ring'\|'custom'`) | `'runic'` |
|
|
888
|
+
| `ariaLabel` | `string` | `'Loading'` |
|
|
889
|
+
| `overlay` (spinner only) | `boolean` | `false` |
|
|
890
|
+
| `loading` (spinner-overlay only) | `boolean` | `false` — toggles the overlay + `aria-busy` |
|
|
891
|
+
|
|
892
|
+
`variant="custom"` renders your own projected markup, still inheriting the size wrapper and
|
|
893
|
+
`--gog-spinner-color` theming.
|
|
894
|
+
|
|
895
|
+
```html
|
|
896
|
+
<gog-spinner-overlay [loading]="isLoading()">
|
|
897
|
+
<app-content-that-loads />
|
|
898
|
+
</gog-spinner-overlay>
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
#### `gog-skeleton`
|
|
902
|
+
|
|
903
|
+
| Input | Type | Default |
|
|
904
|
+
| ----------------- | -------------------------------------------------- | ---------------------------------------------------- |
|
|
905
|
+
| `shape` | `GogSkeletonShape` (`'text'\|'circle'\|'rect'`) | `'text'` |
|
|
906
|
+
| `size` | `GogSize` | `'md'` |
|
|
907
|
+
| `animation` | `GogSkeletonAnimation` (`'pulse'\|'wave'\|'none'`) | `'pulse'` |
|
|
908
|
+
| `width`, `height` | `string \| null` | `null` |
|
|
909
|
+
| `lines` | `number` | `1` — `shape="text"` only, last line renders shorter |
|
|
910
|
+
| `rounded` | `boolean` | `true` |
|
|
911
|
+
| `ariaLabel` | `string \| null` | `null` — decorative (no `role`) unless set |
|
|
912
|
+
|
|
913
|
+
```html
|
|
914
|
+
<gog-skeleton shape="text" [lines]="3" /> <gog-skeleton shape="circle" width="48px" />
|
|
915
|
+
```
|
|
916
|
+
|
|
917
|
+
#### `gog-progressbar`
|
|
918
|
+
|
|
919
|
+
| Input | Type | Default |
|
|
920
|
+
| ----------------- | ---------------------------------------------------------------------------- | --------------- |
|
|
921
|
+
| `value`, `buffer` | `number` (0–100, clamped) | `0` |
|
|
922
|
+
| `mode` | `GogProgressbarMode` (`'determinate'\|'indeterminate'\|'buffer'`) | `'determinate'` |
|
|
923
|
+
| `variant` | `GogProgressbarVariant` (`'accent'\|'success'\|'danger'\|'warning'\|'info'`) | `'accent'` |
|
|
924
|
+
| `size` | `GogSize` | `'md'` |
|
|
925
|
+
| `showValue` | `boolean` | `false` |
|
|
926
|
+
| `ariaLabel` | `string` | `''` |
|
|
927
|
+
|
|
928
|
+
```html
|
|
929
|
+
<gog-progressbar mode="indeterminate" ariaLabel="Loading" />
|
|
930
|
+
<gog-progressbar mode="buffer" [value]="42" [buffer]="70" />
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
#### `gog-divider`
|
|
934
|
+
|
|
935
|
+
| Input | Type | Default |
|
|
936
|
+
| ------------- | --------------------------------------------------- | -------------- |
|
|
937
|
+
| `orientation` | `GogOrientation` | `'horizontal'` |
|
|
938
|
+
| `variant` | `GogDividerVariant` (`'solid'\|'dashed'\|'dotted'`) | `'solid'` |
|
|
939
|
+
| `inset` | `boolean` | `false` |
|
|
940
|
+
|
|
941
|
+
Label is projected content, not an input — put an icon or a `gog-tag` inside it if needed.
|
|
942
|
+
|
|
943
|
+
```html
|
|
944
|
+
<gog-divider>OR</gog-divider>
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
#### `gogTooltip` — directive, not a component
|
|
948
|
+
|
|
949
|
+
Drop on any element — a `gog-*` component's host tag or a plain native one.
|
|
950
|
+
|
|
951
|
+
| Input | Type | Default |
|
|
952
|
+
| --------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
953
|
+
| `gogTooltip` | `string \| TemplateRef \| null` | `null` — content |
|
|
954
|
+
| `gogTooltipPosition` | `GogTooltipPosition` (`'auto'\|'top'\|'bottom'\|'left'\|'right'`) | `'auto'`; via `GOG_CONFIG.tooltip.position` |
|
|
955
|
+
| `gogTooltipShowDelay` | `number \| undefined` | `300`; via `GOG_CONFIG.tooltip.showDelay` |
|
|
956
|
+
| `gogTooltipHideDelay` | `number \| undefined` | `100`; via `GOG_CONFIG.tooltip.hideDelay` |
|
|
957
|
+
| `gogTooltipDisabled` | `boolean` | `false` |
|
|
958
|
+
| `gogTooltipClass` | `string` | `''` — class on the bubble itself, since it's portaled to `<body>` |
|
|
959
|
+
|
|
960
|
+
```html
|
|
961
|
+
<button gogTooltip="Save changes">💾</button> <gog-chip [gogTooltip]="hintTemplate">Beta</gog-chip>
|
|
962
|
+
```
|
|
963
|
+
|
|
964
|
+
### Layout & navigation
|
|
965
|
+
|
|
966
|
+
#### `gog-accordion`
|
|
967
|
+
|
|
968
|
+
| Input | Type | Default |
|
|
969
|
+
| --------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------- |
|
|
970
|
+
| `items` | `GogAccordionItem[]` (`{ id, title, disabled?, [key: string]: unknown }`) | `[]` |
|
|
971
|
+
| `size` | `GogSize` | `'lg'` (not `'md'` — see conventions) |
|
|
972
|
+
| `expandFirst`, `multi`, `loading` | `boolean` | `false` |
|
|
973
|
+
| `skeletonCount` | `number` | `3` — rows shown while `loading` and `items` is still empty |
|
|
974
|
+
| `showChevron` | `boolean` | `true` |
|
|
975
|
+
| `headingLevel` | `2\|3\|4\|5\|6 \| undefined` | `undefined` — wraps headers in `role="heading"` when set |
|
|
976
|
+
|
|
977
|
+
Model: `openIds: ReadonlySet<string | number>`. Output: `gogToggle: { item, open }`.
|
|
978
|
+
|
|
979
|
+
Slots: `<ng-template gogAccordionHeader let-item let-open="open">`,
|
|
980
|
+
`<ng-template gogAccordionContent let-item>`, `<ng-template gogAccordionChevron let-item let-open="open">`.
|
|
981
|
+
This is the library's canonical example of the slot pattern — copy its shape for anything similar.
|
|
982
|
+
|
|
983
|
+
```html
|
|
984
|
+
<gog-accordion [items]="faqItems" [multi]="true">
|
|
985
|
+
<ng-template gogAccordionContent let-item>{{ item.answer }}</ng-template>
|
|
986
|
+
</gog-accordion>
|
|
987
|
+
```
|
|
988
|
+
|
|
989
|
+
#### `gog-collapsible` + `gogCollapsibleTrigger` / `gogCollapsibleContent`
|
|
990
|
+
|
|
991
|
+
**Headless primitive** — owns no markup at all, just open/close state plus two attribute
|
|
992
|
+
directives you place on your own elements. Use this when `gog-accordion`'s opinionated markup
|
|
993
|
+
doesn't fit (e.g. a sidebar nav group).
|
|
994
|
+
|
|
995
|
+
| Input (on `gog-collapsible`) | Type | Default |
|
|
996
|
+
| ---------------------------- | --------- | ---------------------------------------------------------- |
|
|
997
|
+
| `disabled` | `boolean` | `false` |
|
|
998
|
+
| `collapseOnFocusOut` | `boolean` | `false` — close once focus leaves both trigger and content |
|
|
999
|
+
|
|
1000
|
+
Model: `open: boolean`.
|
|
1001
|
+
|
|
1002
|
+
```html
|
|
1003
|
+
<gog-collapsible [(open)]="isOpen">
|
|
1004
|
+
<button gogCollapsibleTrigger>Advanced options</button>
|
|
1005
|
+
<div gogCollapsibleContent>
|
|
1006
|
+
<!-- any markup -->
|
|
1007
|
+
</div>
|
|
1008
|
+
</gog-collapsible>
|
|
1009
|
+
```
|
|
1010
|
+
|
|
1011
|
+
#### `gog-tabs` + `gog-tab`
|
|
1012
|
+
|
|
1013
|
+
| Input (on `gog-tabs`) | Type | Default |
|
|
1014
|
+
| ------------------------ | ------------------------------------------------------ | ---------------------------------------------------- |
|
|
1015
|
+
| `align` | `GogTabsAlign` (`'start'\|'center'\|'end'\|'stretch'`) | `'start'` |
|
|
1016
|
+
| `orientation` | `GogOrientation` | `'horizontal'` |
|
|
1017
|
+
| `size` | `GogSize` | `'md'` |
|
|
1018
|
+
| `fullWidth`, `ariaLabel` | | `false`, `''` |
|
|
1019
|
+
| `scrollActiveIntoView` | `boolean` | `true` |
|
|
1020
|
+
| `showScrollTrack` | `boolean \| undefined` | follows `scrollActiveIntoView` (hidden when it's on) |
|
|
1021
|
+
|
|
1022
|
+
Model: `activeIndex: number`. Output: `gogTabChange: number`.
|
|
1023
|
+
|
|
1024
|
+
| Input (on `gog-tab`) | Type | Default |
|
|
1025
|
+
| -------------------- | --------------------- | ------- |
|
|
1026
|
+
| `label` | `string` | `''` |
|
|
1027
|
+
| `iconName` | `GogIconName \| null` | `null` |
|
|
1028
|
+
| `disabled` | `boolean` | `false` |
|
|
1029
|
+
|
|
1030
|
+
Slots: `<ng-template gogTabHeader let-tab let-active="active">` on `gog-tabs` for custom header
|
|
1031
|
+
markup; `<ng-template gogTabContent>` **inside** a `gog-tab` to make that tab's content **lazy**
|
|
1032
|
+
(built on first activation, then kept alive) instead of the default (rendered immediately,
|
|
1033
|
+
hidden via `[hidden]` while inactive — preserves scroll/input state).
|
|
1034
|
+
|
|
1035
|
+
```html
|
|
1036
|
+
<gog-tabs [(activeIndex)]="tabIndex">
|
|
1037
|
+
<gog-tab label="Profile"><app-profile /></gog-tab>
|
|
1038
|
+
<gog-tab label="Report" iconName="info">
|
|
1039
|
+
<ng-template gogTabContent><app-expensive-report /></ng-template>
|
|
1040
|
+
</gog-tab>
|
|
1041
|
+
</gog-tabs>
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
#### `gog-paginator`
|
|
1045
|
+
|
|
1046
|
+
| Input | Type | Default |
|
|
1047
|
+
| ------------------------------- | ------------------------------------------------ | ------------------------------ |
|
|
1048
|
+
| `fullWidth`, `totalPages` | `boolean`, `number` | `true`, `1` |
|
|
1049
|
+
| `rangeMode` | `GogPaginatorRangeMode` (`'window'\|'ellipsis'`) | `'window'` — see note |
|
|
1050
|
+
| `visiblePages` | `number` | `5` — `'window'` mode only |
|
|
1051
|
+
| `showFirstPage`, `showLastPage` | `boolean` | `false` — `'window'` mode only |
|
|
1052
|
+
| `siblingCount` | `number` | `2` — `'ellipsis'` mode only |
|
|
1053
|
+
| `size` | `GogSize` | `'sm'` |
|
|
1054
|
+
| `disabled`, `ariaLabel` | | `false`, `'Pagination'` |
|
|
1055
|
+
| `totalRecords` | `number \| null` | `null` — see below |
|
|
1056
|
+
| `pageSize` | `model<number>` | `10` — two-way bindable |
|
|
1057
|
+
| `showPageSizeSelect` | `boolean \| undefined` | `false`; via `GOG_CONFIG.paginator` |
|
|
1058
|
+
| `pageSizeOptions` | `number[] \| undefined` | `[10, 20, 30, 40, 50]`; via `GOG_CONFIG.paginator` |
|
|
1059
|
+
|
|
1060
|
+
The step buttons (`'Previous page'`/`'Next page'`) and the per-page names are configured, not
|
|
1061
|
+
input-driven: `GOG_CONFIG.labels.previousPage`/`nextPage`, and `labels.page`, a
|
|
1062
|
+
`(page: number, isCurrent: boolean) => string` formatter defaulting to
|
|
1063
|
+
`` `Page ${page}, current page` `` / `` `Go to page ${page}` ``.
|
|
1064
|
+
|
|
1065
|
+
Models: `page: number` (1-based, self-clamps) and `pageSize: number`.
|
|
1066
|
+
|
|
1067
|
+
**Give it `totalRecords` instead of `totalPages` when you know the row count** — it then derives
|
|
1068
|
+
the page count from `pageSize` itself, which is what removes the
|
|
1069
|
+
`computed(() => Math.ceil(total / size))` a consumer would otherwise have to write *and* keep in
|
|
1070
|
+
sync with the rows-per-page select:
|
|
1071
|
+
|
|
1072
|
+
```html
|
|
1073
|
+
<gog-paginator
|
|
1074
|
+
[(page)]="page"
|
|
1075
|
+
[(pageSize)]="size"
|
|
1076
|
+
[totalRecords]="items().length"
|
|
1077
|
+
[showPageSizeSelect]="true"
|
|
1078
|
+
/>
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
`totalPages` still works and is the right input when the server tells you a page count directly;
|
|
1082
|
+
`totalRecords` wins when both are set. Changing the page size always returns to page 1 — "page 5"
|
|
1083
|
+
of 10-row pages is not "page 5" of 50-row ones, so clamping alone would leave the user somewhere
|
|
1084
|
+
they never asked to be.
|
|
1085
|
+
|
|
1086
|
+
`'window'`: a fixed number of page buttons that slides to keep the current page centered.
|
|
1087
|
+
`'ellipsis'`: first/last pinned, `siblingCount` around the current page, "…" fills the gap
|
|
1088
|
+
(what `gog-table`'s built-in pagination uses).
|
|
1089
|
+
|
|
1090
|
+
```html
|
|
1091
|
+
<gog-paginator [(page)]="page" [totalPages]="totalPages" />
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
#### `gog-table<T>`
|
|
1095
|
+
|
|
1096
|
+
| Input | Type | Default |
|
|
1097
|
+
| ----------------------------- | ----------------------------- | --------------------------------- |
|
|
1098
|
+
| `value` | `T[]` | `[]` |
|
|
1099
|
+
| `fullWidth` | `boolean` | `true` |
|
|
1100
|
+
| `pageSize` | `model<number>` | `0` (no pagination) — two-way |
|
|
1101
|
+
| `showPageSizeSelect` | `boolean \| undefined` | `false`; forwarded to the paginator |
|
|
1102
|
+
| `pageSizeOptions` | `number[] \| undefined` | `[10, 20, 30, 40, 50]`; forwarded |
|
|
1103
|
+
| `showRowNumbers`, `showTotal` | `boolean` | `true`, `false` |
|
|
1104
|
+
| `emptyPlaceholder` | `string` | `'-'` |
|
|
1105
|
+
| `paginatorPosition` | `'left'\|'center'\|'right'` | `'center'` |
|
|
1106
|
+
| `totalPosition` | `'left'\|'right'\|'opposite'` | `'opposite'` |
|
|
1107
|
+
| `loading` | `boolean` | `false` |
|
|
1108
|
+
| `showColumnBorders` | `boolean` | `false` |
|
|
1109
|
+
| `stickyHeader` | `boolean` | `false` |
|
|
1110
|
+
| `size` | `GogSize` | `'lg'` (row density — not `'md'`) |
|
|
1111
|
+
| `lazy` | `boolean` | `false` — see below |
|
|
1112
|
+
| `totalRecords` | `number \| null` | `null` — `lazy` only |
|
|
1113
|
+
| `selectionMode` | `GogTableSelectionMode` | `'none'` |
|
|
1114
|
+
| `selection` | `model<T[]>` | `[]` — two-way bindable |
|
|
1115
|
+
| `dataKey` | `string` | `''` — row identity field |
|
|
1116
|
+
| `showSelectionColumn` | `boolean` | `true` (once selection is on) |
|
|
1117
|
+
| `interactiveRows` | `boolean` | `false` |
|
|
1118
|
+
|
|
1119
|
+
Outputs: `gogSortChange: GogTableSortEvent` (`{ field, direction }`, `{ field: '', direction:
|
|
1120
|
+
null }` when the third click clears it), `gogPageChange: number` (1-based; **does not fire** on
|
|
1121
|
+
first render, nor for the page reset a new sort causes — that reset belongs to the sort),
|
|
1122
|
+
`gogRowClick: GogTableRowClickEvent<T>` (`{ row, index, originalEvent }`).
|
|
1123
|
+
|
|
1124
|
+
Columns are declared as **projected `gog-column` children**, not an input array:
|
|
1125
|
+
|
|
1126
|
+
```html
|
|
1127
|
+
<gog-table [value]="rows">
|
|
1128
|
+
<gog-column field="name" header="Name" sortable="true" />
|
|
1129
|
+
<gog-column field="email" header="Email" />
|
|
1130
|
+
<gog-column field="status" header="Status">
|
|
1131
|
+
<ng-template gogColumnBody let-row let-value="value">
|
|
1132
|
+
<gog-tag [variant]="row.active ? 'success' : 'danger'">{{ value }}</gog-tag>
|
|
1133
|
+
</ng-template>
|
|
1134
|
+
</gog-column>
|
|
1135
|
+
</gog-table>
|
|
1136
|
+
```
|
|
1137
|
+
|
|
1138
|
+
##### Server-driven tables — `lazy`
|
|
1139
|
+
|
|
1140
|
+
By default the table owns the whole data set: it sorts `value` and slices the page itself. With
|
|
1141
|
+
`[lazy]="true"` it does neither — `value` **is** the current page, already sorted, and the table
|
|
1142
|
+
renders it untouched. Supply `totalRecords` (without it the table cannot know how many pages
|
|
1143
|
+
exist, so pagination stays hidden and it warns in dev), then refetch from the two outputs:
|
|
1144
|
+
|
|
1145
|
+
```html
|
|
1146
|
+
<gog-table
|
|
1147
|
+
[value]="page()"
|
|
1148
|
+
[lazy]="true"
|
|
1149
|
+
[totalRecords]="total()"
|
|
1150
|
+
[pageSize]="20"
|
|
1151
|
+
[loading]="loading()"
|
|
1152
|
+
dataKey="id"
|
|
1153
|
+
(gogSortChange)="sort.set($event); reload()"
|
|
1154
|
+
(gogPageChange)="pageNumber.set($event); reload()"
|
|
1155
|
+
>
|
|
1156
|
+
```
|
|
1157
|
+
|
|
1158
|
+
Row numbers still count from the current page (`(page - 1) * pageSize + i + 1`), and `showTotal`
|
|
1159
|
+
reports `totalRecords` rather than `value.length`. **Do not** sort or slice `value` yourself in
|
|
1160
|
+
addition — that is what the flag turns off.
|
|
1161
|
+
|
|
1162
|
+
##### Rows per page
|
|
1163
|
+
|
|
1164
|
+
`pageSize` is a **`model`**, not an input: `[pageSize]="20"` works exactly as before, and
|
|
1165
|
+
`[(pageSize)]="size"` becomes possible. That is what makes the rows-per-page select work with no
|
|
1166
|
+
wiring — the table binds its own model straight to the paginator's, the select writes back
|
|
1167
|
+
through it, and there is no intermediate signal to keep in sync in either direction.
|
|
1168
|
+
|
|
1169
|
+
```html
|
|
1170
|
+
<!-- off by default; turn it on per table, or app-wide via GOG_CONFIG.paginator -->
|
|
1171
|
+
<gog-table [value]="rows" [(pageSize)]="size" [showPageSizeSelect]="true" [pageSizeOptions]="[5, 10, 20]">
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
Changing the size returns to page 1 and does **not** emit `gogPageChange` — the consumer already
|
|
1175
|
+
knows from `pageSizeChange`, and firing both would make a lazy table fetch twice. In `lazy` mode
|
|
1176
|
+
`pageSizeChange` is the refetch signal; bind `[pageSize]` + `(pageSizeChange)` rather than the
|
|
1177
|
+
banana-box if you need to act on it.
|
|
1178
|
+
|
|
1179
|
+
The footer stays visible at a single page whenever the select is on — hiding it would strand the
|
|
1180
|
+
user on whatever size produced that one page, with no control left to pick a smaller one.
|
|
1181
|
+
|
|
1182
|
+
##### Selection
|
|
1183
|
+
|
|
1184
|
+
`selectionMode` turns it on; `[(selection)]` is always a `T[]`, including in `'single'` mode
|
|
1185
|
+
where it holds zero or one row — one shape rather than a union to narrow on every read.
|
|
1186
|
+
|
|
1187
|
+
```html
|
|
1188
|
+
<gog-table [value]="rows" selectionMode="multiple" [(selection)]="selected" dataKey="id">
|
|
1189
|
+
```
|
|
1190
|
+
|
|
1191
|
+
- **Set `dataKey`.** Without it rows are matched by object identity, so any refetch that produces
|
|
1192
|
+
new objects silently drops the selection. It is also the `@for` track key, which is what lets
|
|
1193
|
+
the DOM survive a refetch instead of being rebuilt.
|
|
1194
|
+
- The checkbox column renders automatically (`showSelectionColumn` to turn it off, e.g. for a
|
|
1195
|
+
table that selects by row click — pair that with `interactiveRows`).
|
|
1196
|
+
- The header select-all appears only in `'multiple'` mode and covers **the current page**, never
|
|
1197
|
+
the whole data set: in `lazy` mode the table has never seen the other pages, and a control that
|
|
1198
|
+
behaved differently between the two modes would be worse than either.
|
|
1199
|
+
|
|
1200
|
+
##### Clickable rows
|
|
1201
|
+
|
|
1202
|
+
`gogRowClick` fires on a click regardless, but a `<tr>` is not focusable, so on its own that is a
|
|
1203
|
+
mouse-only affordance. `interactiveRows` makes rows focusable and styles them as clickable, and
|
|
1204
|
+
Enter/Space then activate the focused row. If the action is really "open this one thing", a link
|
|
1205
|
+
or button inside a cell is better than a whole-row target.
|
|
1206
|
+
|
|
1207
|
+
`gog-column` inputs: `field` (required, dot-paths ok), `header`, `sortable` (default `false`),
|
|
1208
|
+
`width`/`minWidth`/`maxWidth`, `comparator` (custom `(a, b) => number`, defaults to a
|
|
1209
|
+
locale-aware collator for strings). Slots inside a column: `<ng-template gogColumnBody let-row let-value="value" let-index="index">`,
|
|
1210
|
+
`<ng-template gogColumnHeader let-header let-field="field">`.
|
|
1211
|
+
|
|
1212
|
+
**Sorting, empty/loading states and pagination are all built in** — sortable columns toggle
|
|
1213
|
+
asc → desc → unsorted on click, `loading` shows a spinner in place of rows, an empty `value`
|
|
1214
|
+
shows `emptyPlaceholder`, and `pageSize > 0` turns on the internal paginator automatically. You
|
|
1215
|
+
don't need to hand-roll any of this.
|
|
1216
|
+
|
|
1217
|
+
There is **no typed row-selection API** in the current version — if you need it, track
|
|
1218
|
+
selection yourself (e.g. a `Set` keyed by row id) and render a `gogColumnBody` checkbox column.
|
|
1219
|
+
|
|
1220
|
+
#### `gog-scroll`
|
|
1221
|
+
|
|
1222
|
+
Drop-in replacement for `overflow: auto` — content still scrolls natively (wheel, touch,
|
|
1223
|
+
keyboard); only the browser's own scrollbar chrome is replaced with a themeable overlay thumb.
|
|
1224
|
+
Used internally by several other components (`gog-dialog`'s body, `gog-select`'s panel,
|
|
1225
|
+
`gog-tabs`' header row) and equally usable directly in your own markup for any scrollable
|
|
1226
|
+
region — the library's official recommendation over a raw `overflow-x`/`overflow-y`.
|
|
1227
|
+
|
|
1228
|
+
| Input | Type | Default |
|
|
1229
|
+
| -------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- |
|
|
1230
|
+
| `axis` | `GogScrollAxis` (`'vertical'\|'horizontal'\|'both'`) | `'vertical'` |
|
|
1231
|
+
| `size` | `GogScrollSize \| undefined` (`'normal'\|'thin'`) | `'normal'`; via `GOG_CONFIG.scroll.size` |
|
|
1232
|
+
| `autoHide` | `boolean \| undefined` | `true`; via `GOG_CONFIG.scroll.autoHide` |
|
|
1233
|
+
| `hideDelay` | `number \| undefined` | `800`; via `GOG_CONFIG.scroll.hideDelay` |
|
|
1234
|
+
| `reachThreshold` | `number` | `0` |
|
|
1235
|
+
| `focusable` | `boolean` | `true` — turn off when the parent already owns focus (a dialog with its own focus trap) |
|
|
1236
|
+
| `ariaLabel` | `string` | `''` |
|
|
1237
|
+
| `overscrollBehavior` | `GogScrollOverscrollBehavior \| undefined` (`'auto'\|'contain'\|'none'`) | `'auto'`; via `GOG_CONFIG.scroll.overscrollBehavior` |
|
|
1238
|
+
| `showTrack` | `boolean \| undefined` | `true`; via `GOG_CONFIG.scroll.showTrack` |
|
|
1239
|
+
|
|
1240
|
+
Outputs: `gogScroll: GogScrollMetrics`, `gogReachStart`/`gogReachEnd: 'vertical'|'horizontal'`.
|
|
1241
|
+
Methods (via template ref): `scrollTo(options)`, `scrollToTop()`, `scrollToBottom()`,
|
|
1242
|
+
`scrollToLeft()`, `scrollToRight()`.
|
|
1243
|
+
|
|
1244
|
+
```html
|
|
1245
|
+
<gog-scroll size="thin" [focusable]="false" overscrollBehavior="contain" style="max-height: 320px">
|
|
1246
|
+
<!-- content that might overflow -->
|
|
1247
|
+
</gog-scroll>
|
|
1248
|
+
```
|
|
1249
|
+
|
|
1250
|
+
### Overlays
|
|
1251
|
+
|
|
1252
|
+
#### `gog-dialog`
|
|
1253
|
+
|
|
1254
|
+
A **single** `<gog-dialog />` renders **every** dialog `DialogService.open(...)` creates —
|
|
1255
|
+
place it once, typically in your root app component's template, not per-page and not per-dialog
|
|
1256
|
+
call:
|
|
1257
|
+
|
|
1258
|
+
```html
|
|
1259
|
+
<!-- app.html -->
|
|
1260
|
+
<router-outlet />
|
|
1261
|
+
<gog-dialog />
|
|
1262
|
+
```
|
|
1263
|
+
|
|
1264
|
+
It has no inputs of its own — everything is driven through `DialogService` (see
|
|
1265
|
+
[Services](#services) above). Supports nesting, dragging (when `draggable !== false` and the
|
|
1266
|
+
dialog has a title or close button), a focus trap for modal dialogs, `Escape` to close (when
|
|
1267
|
+
`closable !== false`), and click-outside-to-close on the backdrop.
|
|
1268
|
+
|
|
1269
|
+
#### `gog-toast` / `gog-toast-container`
|
|
1270
|
+
|
|
1271
|
+
Same pattern — place **one** `<gog-toast-container />`, typically in the root component:
|
|
1272
|
+
|
|
1273
|
+
```html
|
|
1274
|
+
<gog-toast-container [maxVisiblePerPosition]="5" />
|
|
1275
|
+
```
|
|
1276
|
+
|
|
1277
|
+
`maxVisiblePerPosition` (default `5`) caps how many toasts stack at once per corner; the rest
|
|
1278
|
+
queue. Individual `gog-toast` instances are rendered internally by the container from
|
|
1279
|
+
`ToastService.toasts()` — you don't place these yourself. Toasts auto-dismiss after their
|
|
1280
|
+
`duration` unless `isSticky`; hovering pauses the countdown (front-of-stack toast only).
|
|
1281
|
+
|
|
1282
|
+
Announcements come from two permanently-mounted, visually-hidden live regions the container
|
|
1283
|
+
owns — polite, and assertive for `error`/`warning`. The toasts themselves carry no
|
|
1284
|
+
`role`/`aria-live`: a live region created in the same tick as its text is routinely skipped by
|
|
1285
|
+
screen readers, and a second region would announce everything twice. Don't add either back.
|
|
1286
|
+
|
|
1287
|
+
---
|
|
1288
|
+
|
|
1289
|
+
## Deprecated patterns — do not use in new code
|
|
1290
|
+
|
|
1291
|
+
These still work (nothing breaks if you use them), but are marked `@deprecated` and **will be
|
|
1292
|
+
removed** on the stated schedule. Don't generate new code using any of them — use the listed
|
|
1293
|
+
replacement instead.
|
|
1294
|
+
|
|
1295
|
+
| Deprecated | Removed in | Replacement |
|
|
1296
|
+
| ---------------------------------------------------------------------------------------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------- |
|
|
1297
|
+
| `GogSelectOption`, `GogMultiselectOption` type aliases | `21.4.0` | `GogDropdownOption` |
|
|
1298
|
+
| `gog-select`/`gog-multiselect` `chevronTemplate` input | `21.5.0` | `<ng-template gogDropdownChevron>` |
|
|
1299
|
+
| `gog-checkbox` `checkIconTemplate` input | `21.5.0` | `<ng-template gogCheckboxIcon>` |
|
|
1300
|
+
| `gog-tag` `iconTemplate` input | `21.5.0` | `<ng-template gogTagIcon>` |
|
|
1301
|
+
| `gog-multiselect` `clearIconTemplate` input | `21.5.0` | `<ng-template gogMultiselectClearIcon>` |
|
|
1302
|
+
| `gog-inputfield` `iconStartTemplate`/`iconEndTemplate`/`iconStartFn`/`iconEndFn`/`iconStartLabel`/`iconEndLabel` | `21.5.0` | `<span gogInputAddonStart>`/`<span gogInputAddonEnd>` (or a `<button>` with its own handler) |
|
|
1303
|
+
| `gog-table`'s `[template]` attribute (`<ng-template template="field" type="body">`) | `21.5.0` | `<ng-template gogColumnBody>` / `<ng-template gogColumnHeader>` declared **inside** the matching `<gog-column>` |
|
|
1304
|
+
| `<column>` selector / `Column` export | `21.5.0` | `<gog-column>` / `GogColumn` |
|
|
1305
|
+
|
|
1306
|
+
The general rule they all follow: a `TemplateRef` **input** or a string-keyed lookup is the old
|
|
1307
|
+
shape; a **projected content directive with a typed context**, declared where it's used, is the
|
|
1308
|
+
current one. If you're about to write `fooTemplate` next to an existing `foo` input, or key
|
|
1309
|
+
something off a string that has to match another string elsewhere, that's this exact
|
|
1310
|
+
anti-pattern — reach for a slot directive instead.
|
|
1311
|
+
|
|
1312
|
+
## Full type reference
|
|
1313
|
+
|
|
1314
|
+
Shared enum-like types (`import type { ... } from '@guildofgleks/ui'`):
|
|
1315
|
+
|
|
1316
|
+
| Type | Values |
|
|
1317
|
+
| ----------------------------- | --------------------------------------------------------------------------------------------- |
|
|
1318
|
+
| `GogSize` | `'xsm' \| 'sm' \| 'md' \| 'lg' \| 'slg'` |
|
|
1319
|
+
| `GogVariant` | `'primary' \| 'secondary' \| 'outline' \| 'ghost'` |
|
|
1320
|
+
| `GogTagVariant` | `'success' \| 'danger' \| 'warning' \| 'info'` |
|
|
1321
|
+
| `GogOrientation` | `'horizontal' \| 'vertical'` |
|
|
1322
|
+
| `GogTagShape` | `'rounded' \| 'pill'` |
|
|
1323
|
+
| `GogSpinnerVariant` | `'runic' \| 'ring' \| 'custom'` |
|
|
1324
|
+
| `GogSkeletonShape` | `'text' \| 'circle' \| 'rect'` |
|
|
1325
|
+
| `GogSkeletonAnimation` | `'pulse' \| 'wave' \| 'none'` |
|
|
1326
|
+
| `GogPaginatorRangeMode` | `'window' \| 'ellipsis'` |
|
|
1327
|
+
| `GogScrollAxis` | `'vertical' \| 'horizontal' \| 'both'` |
|
|
1328
|
+
| `GogScrollSize` | `'normal' \| 'thin'` |
|
|
1329
|
+
| `GogScrollOverscrollBehavior` | `'auto' \| 'contain' \| 'none'` |
|
|
1330
|
+
| `GogTooltipPosition` | `'auto' \| 'top' \| 'bottom' \| 'left' \| 'right'` |
|
|
1331
|
+
| `GogFloatLabelVariant` | `'none' \| 'in' \| 'on' \| 'over'` |
|
|
1332
|
+
| `GogDropdownFilterPosition` | `'top' \| 'bottom'` |
|
|
1333
|
+
| `GogDividerVariant` | `'solid' \| 'dashed' \| 'dotted'` |
|
|
1334
|
+
| `GogBadgePosition` | `'top-end' \| 'top-start' \| 'bottom-end' \| 'bottom-start'` |
|
|
1335
|
+
| `GogProgressbarMode` | `'determinate' \| 'indeterminate' \| 'buffer'` |
|
|
1336
|
+
| `GogProgressbarVariant` | `'accent' \| 'success' \| 'danger' \| 'warning' \| 'info'` |
|
|
1337
|
+
| `GogButtonToggleAppearance` | `'joined' \| 'separated'` |
|
|
1338
|
+
| `GogTabsAlign` | `'start' \| 'center' \| 'end' \| 'stretch'` |
|
|
1339
|
+
| `GogDateSelectionMode` | `'single' \| 'range'` |
|
|
1340
|
+
| `GogHourFormat` | `'12' \| '24'` |
|
|
1341
|
+
| `GogTextareaResize` | `'vertical' \| 'horizontal' \| 'both' \| 'none'` |
|
|
1342
|
+
| `GogInputType` | `'text' \| 'password' \| 'email' \| 'number' \| 'search' \| 'tel' \| 'url' \| 'date' \| 'time' \| 'datetime-local'` |
|
|
1343
|
+
| `GogInputMode` | `'none' \| 'text' \| 'decimal' \| 'numeric' \| 'tel' \| 'search' \| 'email' \| 'url'` |
|
|
1344
|
+
| `GogTableSelectionMode` | `'none' \| 'single' \| 'multiple'` |
|
|
1345
|
+
| `GogTableSortEvent` | `{ field: string; direction: SortDirection }` |
|
|
1346
|
+
| `GogTableRowClickEvent<T>` | `{ row: T; index: number; originalEvent: MouseEvent \| KeyboardEvent }` |
|
|
1347
|
+
| `GogErrorDisplay` | `'auto' \| 'manual'` |
|
|
1348
|
+
| `GogDropdownDirection` | `'auto' \| 'up' \| 'down'` |
|
|
1349
|
+
| `GogTooltipSide` | `'top' \| 'bottom' \| 'left' \| 'right'` (resolved form of `GogTooltipPosition`, no `'auto'`) |
|
|
1350
|
+
| `GogBuiltinIconName` | the 20 glyphs the package ships — see [`gog-icon`](#gog-icon) |
|
|
1351
|
+
| `GogIconName` | `GogBuiltinIconName \| (string & {})` — built-ins plus anything registered via `provideGogIcons` |
|