@norconsult-digital-public/isypixel 2.0.2-canary.8 → 2.0.2-canary.9
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/dist/docs/web-components/ip-date-display/llm.md +161 -0
- package/dist/docs/web-components/services/locale/llm.md +62 -0
- package/dist/llm.md +21 -19
- package/dist/types/components/ip-date-display/i18n.d.ts +4 -0
- package/dist/types/components/ip-date-display/ip-date-display.d.ts +29 -0
- package/dist/types/components.d.ts +82 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/services/i18n/i18n.d.ts +3 -0
- package/dist/types/services/index.d.ts +2 -0
- package/dist/types/services/locale/locale.d.ts +23 -0
- package/dist/web-components/components/index.js +1 -1
- package/dist/web-components/components/ip-date-display.d.ts +11 -0
- package/dist/web-components/components/ip-date-display.js +1 -0
- package/dist/web-components/components/ip-main-menu-group.js +1 -1
- package/dist/web-components/components/ip-main-menu-item.js +1 -1
- package/dist/web-components/components/ip-main-menu-section.js +1 -1
- package/dist/web-components/components/ip-main-menu-toggle.js +1 -1
- package/dist/web-components/components/ip-main-menu.js +1 -1
- package/dist/web-components/components/p-6Y3JP5Mp.js +1 -0
- package/dist/web-components/components/{p-Ba5PDZcO.js → p-8xxrpIeZ.js} +1 -1
- package/dist/web-components/components/{p-Z_KsG5lc.js → p-B7OyzFE9.js} +1 -1
- package/dist/web-components/components/p-CFwDQCcr.js +1 -0
- package/dist/web-components/components/p-DefPpKsB.js +1 -0
- package/dist/web-components/components/p-DnTzptWz.js +1 -0
- package/dist/web-components/components/{p-CDL6v2R_.js → p-DvqClY_a.js} +1 -1
- package/dist/web-components/components/{p-BcS76vWO.js → p-FtNC-zkT.js} +1 -1
- package/dist/web-components/components/p-iNLo7cGa.js +1 -0
- package/dist/web-components/components/p-npk6jupt.js +1 -0
- package/dist/web-components/generated/angular/components.d.ts +29 -0
- package/dist/web-components/generated/angular/components.js +54 -0
- package/dist/web-components/generated/angular/components.ts +44 -0
- package/dist/web-components/generated/angular/index.d.ts +1 -1
- package/dist/web-components/generated/angular/index.js +1 -0
- package/dist/web-components/generated/angular/index.ts +1 -0
- package/dist/web-components/generated/react/components.d.ts +3 -0
- package/dist/web-components/generated/react/components.js +9 -0
- package/dist/web-components/generated/react/components.ts +12 -0
- package/dist/web-components/generated/svelte/components.d.ts +2 -0
- package/dist/web-components/generated/vue/components.d.ts +1 -0
- package/dist/web-components/generated/vue/components.js +8 -0
- package/dist/web-components/generated/vue/components.ts +10 -0
- package/llms.txt +2 -0
- package/package.json +1 -1
- package/dist/web-components/components/p-BrE_t6WH.js +0 -1
- package/dist/web-components/components/p-C8zDW_sy.js +0 -1
- package/dist/web-components/components/p-ClvSUrIV.js +0 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# ip-date-display
|
|
2
|
+
|
|
3
|
+
A presentational component that displays a date formatted for reading. It supports a selectable date detail level (`dateFormat`), optional time (`timeFormat`), and a `variant` that sets the text colour: three neutral emphasis levels or three semantic colours. An optional leading `icon` slot lets the consumer add an indicator. Use it for deadlines, completion dates, and other dates that should be emphasised by state.
|
|
4
|
+
|
|
5
|
+
The component is purely presentational: it is not interactive, emits no events, and does not participate in forms. The `variant` is set by the consumer, not computed internally.
|
|
6
|
+
|
|
7
|
+
The locale is read reactively from `PixelLocaleService`. There is no `locale` prop. Calling `PixelLocaleService.setLocale(...)` re-renders the date in the new locale automatically.
|
|
8
|
+
|
|
9
|
+
**Storybook:** https://pixel.isy.no/storybook/?path=/docs/core-ui-ip-date-display-usage--docs
|
|
10
|
+
|
|
11
|
+
> This component requires ISY Pixel global styles to render correctly. Always remind the user to verify that styles are imported in their global stylesheet. See `llm.md` in the package root for style import options.
|
|
12
|
+
|
|
13
|
+
## Attributes
|
|
14
|
+
|
|
15
|
+
| Attribute | Type | Default | Values | Description |
|
|
16
|
+
| ------------ | ------ | ----------- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| `date` | string | `""` | ISO 8601 date or datetime | The date to display, e.g. `"2025-08-19"` or `"2025-08-19T14:30"`. Formatted internally. An empty value renders nothing; an unparseable value renders a localized "Invalid date" fallback. |
|
|
18
|
+
| `dateFormat` | string | `"short"` | `"short"`, `"medium"`, `"long"` | Date detail level. Maps to the `Intl.DateTimeFormat` `dateStyle` option. |
|
|
19
|
+
| `timeFormat` | string | `"none"` | `"none"`, `"short"`, `"medium"` | Whether and how detailed the time is shown. Maps to `Intl.DateTimeFormat` `timeStyle`; `"none"` shows no time. Only applies when `date` has a time component. |
|
|
20
|
+
| `variant` | string | `"primary"` | `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"error"` | Visual treatment. `primary`/`secondary`/`tertiary` are neutral emphasis levels; `success`/`warning`/`error` colour the date. The slotted icon inherits this colour. The semantic colour is generic: use `label` to convey its meaning. |
|
|
21
|
+
| `label` | string | `""` | Any string | Optional accessible label describing what a semantic variant means, e.g. `"Overdue"` or `"Do not start before"`. Rendered as visually hidden text. |
|
|
22
|
+
|
|
23
|
+
## Slots
|
|
24
|
+
|
|
25
|
+
| Slot | Description |
|
|
26
|
+
| ------ | ------------------------------------------------------------------------------------------------------------------------ |
|
|
27
|
+
| `icon` | Optional leading icon shown before the date. Decorative (`aria-hidden`); inherits the variant colour via `currentColor`. |
|
|
28
|
+
|
|
29
|
+
## Events
|
|
30
|
+
|
|
31
|
+
None. Purely presentational.
|
|
32
|
+
|
|
33
|
+
## Formatting
|
|
34
|
+
|
|
35
|
+
The date is formatted with `Intl.DateTimeFormat(PixelLocaleService.getLocale(), { dateStyle, timeStyle })`.
|
|
36
|
+
|
|
37
|
+
| `dateFormat` / `timeFormat` | `nb-NO` | `en-US` |
|
|
38
|
+
| --------------------------- | --------------------------- | ---------------------------- |
|
|
39
|
+
| `short` / `none` | `19.08.2025` | `8/19/25` |
|
|
40
|
+
| `short` / `short` | `19.08.2025, 14:30` | `8/19/25, 2:30 PM` |
|
|
41
|
+
| `long` / `short` | `19. august 2025 kl. 14:30` | `August 19, 2025 at 2:30 PM` |
|
|
42
|
+
|
|
43
|
+
- `timeFormat` only has an effect when `date` carries a time component (an ISO datetime such as `2025-08-19T14:30`). A date-only value ignores `timeFormat`.
|
|
44
|
+
- Date-only values are formatted in UTC so a timezone-shifted midnight cannot move the displayed calendar day.
|
|
45
|
+
- An empty `date` renders nothing. A non-empty but unparseable `date` renders a localized "Invalid date" fallback.
|
|
46
|
+
|
|
47
|
+
## Accessibility
|
|
48
|
+
|
|
49
|
+
- The date renders inside a `<time datetime="...">` element. The `datetime` attribute reflects the full ISO value passed in `date`, including the time when present.
|
|
50
|
+
- A semantic variant's colour is generic and not conveyed to assistive tech on its own. Set `label` to describe what it means (e.g. "Overdue"); it is announced as visually hidden text. Without a `label`, a semantic colour carries no meaning for screen readers.
|
|
51
|
+
- The slotted `icon` is decorative and marked `aria-hidden`. It reinforces the variant visually but carries no meaning for screen readers.
|
|
52
|
+
- When `date` is unparseable, the fallback renders only the localized "Invalid date" text: neither the slotted `icon` nor a `label` is shown, since neither applies to an error state.
|
|
53
|
+
|
|
54
|
+
## Localisation
|
|
55
|
+
|
|
56
|
+
The visible "Invalid date" fallback ships in English and Norwegian (`nb-NO`) and is resolved through `PixelI18nService`, the same mechanism as other Pixel components. Override it with `PixelI18nService.setCustomLanguage({ 'ip-date-display': { ... } })`. The `label` is not localised by the component: the consumer supplies it in the correct language.
|
|
57
|
+
|
|
58
|
+
| Key | `en` | `nb-NO` |
|
|
59
|
+
| ------------- | ------------ | ------------ |
|
|
60
|
+
| `invalidDate` | Invalid date | Ugyldig dato |
|
|
61
|
+
|
|
62
|
+
## Design tokens
|
|
63
|
+
|
|
64
|
+
> The `success`, `warning`, and `error` variants use temporary non-adaptive primitive stand-ins. No contrast-approved semantic tokens for these exist in Figma yet, so suitable `extended/*` shades are used and marked `//TODO` in the SCSS. The final tokens and WCAG contrast are resolved in the post-summer design cleanup.
|
|
65
|
+
|
|
66
|
+
| SCSS variable | Role |
|
|
67
|
+
| ----------------------------------------- | ----------------------------------------------- |
|
|
68
|
+
| `$ip_color_text_primary_black` | Text colour for `variant="primary"` |
|
|
69
|
+
| `$ip_color_text_secondary_default` | Text colour for `variant="secondary"` |
|
|
70
|
+
| `$ip_color_text_tertiary_default` | Text colour for `variant="tertiary"` |
|
|
71
|
+
| `$ip_color_extended_green-950` | Text colour for `variant="success"` (temporary) |
|
|
72
|
+
| `$ip_color_extended_yellow-950` | Text colour for `variant="warning"` (temporary) |
|
|
73
|
+
| `$ip_color_extended_red-600` | Text colour for `variant="error"` (temporary) |
|
|
74
|
+
| `$ip_typography_body_font_family_default` | Date font family |
|
|
75
|
+
| `$ip_typography_body_font_size_small` | Date font size |
|
|
76
|
+
| `$ip_typography_body_font_weight_default` | Date font weight |
|
|
77
|
+
| `$ip_spacing_space_100` | Gap between a slotted icon and the date |
|
|
78
|
+
|
|
79
|
+
## Usage
|
|
80
|
+
|
|
81
|
+
### HTML
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
import '@norconsult-digital-public/isypixel/web-components/ip-date-display.js';
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<ip-date-display date="2025-08-19" date-format="long" variant="error" label="Overdue">
|
|
89
|
+
<i slot="icon" class="fas fa-triangle-exclamation"></i>
|
|
90
|
+
</ip-date-display>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### React
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
import { IpDateDisplay } from '@norconsult-digital-public/isypixel/web-components/react';
|
|
97
|
+
|
|
98
|
+
<IpDateDisplay date='2025-08-19' dateFormat='long' variant='error' label='Overdue'>
|
|
99
|
+
<i slot='icon' className='fas fa-triangle-exclamation' />
|
|
100
|
+
</IpDateDisplay>;
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Vue
|
|
104
|
+
|
|
105
|
+
```vue
|
|
106
|
+
<script setup lang="ts">
|
|
107
|
+
import { IpDateDisplay } from '@norconsult-digital-public/isypixel/web-components/vue';
|
|
108
|
+
</script>
|
|
109
|
+
|
|
110
|
+
<template>
|
|
111
|
+
<IpDateDisplay date="2025-08-19" date-format="long" variant="error" label="Overdue">
|
|
112
|
+
<i slot="icon" class="fas fa-triangle-exclamation" />
|
|
113
|
+
</IpDateDisplay>
|
|
114
|
+
</template>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Angular
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import { IpDateDisplay } from '@norconsult-digital-public/isypixel/web-components/angular';
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```html
|
|
124
|
+
<ip-date-display date="2025-08-19" date-format="long" variant="error" label="Overdue">
|
|
125
|
+
<i slot="icon" class="fas fa-triangle-exclamation"></i>
|
|
126
|
+
</ip-date-display>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Svelte
|
|
130
|
+
|
|
131
|
+
```svelte
|
|
132
|
+
<script lang="ts">
|
|
133
|
+
import '@norconsult-digital-public/isypixel/web-components/ip-date-display.js';
|
|
134
|
+
</script>
|
|
135
|
+
|
|
136
|
+
<ip-date-display date="2025-08-19" date-format="long" variant="error" label="Overdue">
|
|
137
|
+
<i slot="icon" class="fas fa-triangle-exclamation"></i>
|
|
138
|
+
</ip-date-display>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Blazor
|
|
142
|
+
|
|
143
|
+
> Attribute names must be **kebab-case** in Blazor HTML.
|
|
144
|
+
|
|
145
|
+
Copy `ip-date-display.js` to `wwwroot/lib/isypixel/components/` at build time. See `llm.md` in the package root for the MSBuild target.
|
|
146
|
+
|
|
147
|
+
```html
|
|
148
|
+
<script type="module" src="lib/isypixel/components/ip-date-display.js"></script>
|
|
149
|
+
|
|
150
|
+
<ip-date-display date="2025-08-19" date-format="long" variant="error" label="Overdue">
|
|
151
|
+
<i slot="icon" class="fas fa-triangle-exclamation"></i>
|
|
152
|
+
</ip-date-display>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Set the locale
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import { PixelLocaleService } from '@norconsult-digital-public/isypixel/web-components/services';
|
|
159
|
+
|
|
160
|
+
PixelLocaleService.setLocale('nb-NO'); // all mounted ip-date-display elements re-render
|
|
161
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# PixelLocaleService
|
|
2
|
+
|
|
3
|
+
Static service holding the application's active formatting locale. Used by components that format values with `Intl` (dates now; numbers, currency, and relative time later). Independent of `PixelI18nService`: locale owns formatting (an open BCP 47 set), i18n owns translations (a closed language set).
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { PixelLocaleService } from '@norconsult-digital-public/isypixel/web-components/services';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## API
|
|
12
|
+
|
|
13
|
+
All methods operate on a reactive `@stencil/store`. Calling `setLocale` or `resetLocale` triggers an **automatic re-render** of every mounted Pixel component that reads the locale in `render()`. No page reload, no manual refresh.
|
|
14
|
+
|
|
15
|
+
| Method | Signature | Description |
|
|
16
|
+
| ------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| `setLocale` | `(locale: string) => void` | Sets the active locale (BCP 47, e.g. `'nb-NO'`, `'en-US'`). Expects a valid locale string; the input is not validated at runtime. Re-renders all components using it. |
|
|
18
|
+
| `resetLocale` | `() => void` | Clears the active locale so formatting follows the runtime/browser locale again. Re-renders all components using it. |
|
|
19
|
+
| `getLocale` | `() => string \| undefined` | Returns the current locale. `undefined` means formatting follows the environment. |
|
|
20
|
+
|
|
21
|
+
## Behaviour
|
|
22
|
+
|
|
23
|
+
- **Default:** no locale set. Formatting follows the browser/runtime locale (`Intl` called with `undefined`). Call `resetLocale` to return to this state.
|
|
24
|
+
- **Type:** `string`. No closed enum. BCP 47 is an open set; the library does not maintain a list of allowed locales.
|
|
25
|
+
- **Reactivity:** internal `@stencil/store`, same principle as i18n. Components read the locale inside `render()` and re-render automatically on `setLocale` or `resetLocale`.
|
|
26
|
+
|
|
27
|
+
## Usage examples
|
|
28
|
+
|
|
29
|
+
### Set the locale
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { PixelLocaleService } from '@norconsult-digital-public/isypixel/web-components/services';
|
|
33
|
+
|
|
34
|
+
PixelLocaleService.setLocale('nb-NO');
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Follow the environment
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
PixelLocaleService.resetLocale();
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Read the current locale
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
const locale = PixelLocaleService.getLocale(); // 'nb-NO' | undefined
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Blazor
|
|
50
|
+
|
|
51
|
+
Locale is JavaScript-only. Call from a JS interop entry point or a `.js` file loaded in `index.html`:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
import { PixelLocaleService } from '@norconsult-digital-public/isypixel/web-components/services';
|
|
55
|
+
PixelLocaleService.setLocale('nb-NO');
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Notes
|
|
59
|
+
|
|
60
|
+
- `PixelLocaleService` is intentionally decoupled from `PixelI18nService`. Setting the language does not change the locale, and vice versa. Set both if an app switches its whole UI language.
|
|
61
|
+
- `setLocale` expects a valid BCP 47 string; the input is not validated at runtime. To follow the environment again, call `resetLocale` rather than passing a sentinel value.
|
|
62
|
+
- Reactivity is powered by `@stencil/store`. Components that read `getLocale()` inside `render()` are automatically tracked and re-rendered when `setLocale` or `resetLocale` is called. No manual subscription is required.
|
package/dist/llm.md
CHANGED
|
@@ -169,28 +169,30 @@ In `index.html` `<body>`:
|
|
|
169
169
|
|
|
170
170
|
## Components
|
|
171
171
|
|
|
172
|
-
| Component | Description
|
|
173
|
-
| ---------------------- |
|
|
174
|
-
| `ip-button` | Clickable button with visual variants, loading state, and icon slot
|
|
175
|
-
| `ip-icon-button` | Circular icon-only button with CSS ripple, visual variants, and loading state
|
|
176
|
-
| `ip-tooltip` | Tooltip that wraps a trigger and shows non-interactive content on hover, focus, and Escape
|
|
177
|
-
| `ip-avatar` | Theme-aware avatar with image/fallback/initials/silhouette chain, label, ring, loader, corner slots, and tooltip
|
|
178
|
-
| `ip-avatar-stack` | Overlapping stack of `ip-avatar` elements with overflow collapse into a `+N` counter and a combined names label
|
|
179
|
-
| `ip-icon-count` | Compact inline indicator pairing a slotted icon with a value, e.g. an attachment count or a sensor reading
|
|
180
|
-
| `ip-chip` | Presentational status/tag chip with orthogonal fill and border, a leading icon, a collapsed state, and a remove button
|
|
181
|
-
| `ip-chip-group` | Groups `ip-chip` children as split buttons with one model: display, single, or multiple selection, plus per-chip removable, with focus restoration on keyboard removal
|
|
182
|
-
| `ip-
|
|
183
|
-
| `ip-main-menu
|
|
184
|
-
| `ip-main-menu-
|
|
185
|
-
| `ip-main-menu-
|
|
186
|
-
| `ip-main-menu-
|
|
172
|
+
| Component | Description | Docs |
|
|
173
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
|
|
174
|
+
| `ip-button` | Clickable button with visual variants, loading state, and icon slot | `docs/web-components/ip-button/llm.md` |
|
|
175
|
+
| `ip-icon-button` | Circular icon-only button with CSS ripple, visual variants, and loading state | `docs/web-components/ip-icon-button/llm.md` |
|
|
176
|
+
| `ip-tooltip` | Tooltip that wraps a trigger and shows non-interactive content on hover, focus, and Escape | `docs/web-components/ip-tooltip/llm.md` |
|
|
177
|
+
| `ip-avatar` | Theme-aware avatar with image/fallback/initials/silhouette chain, label, ring, loader, corner slots, and tooltip | `docs/web-components/ip-avatar/llm.md` |
|
|
178
|
+
| `ip-avatar-stack` | Overlapping stack of `ip-avatar` elements with overflow collapse into a `+N` counter and a combined names label | `docs/web-components/ip-avatar-stack/llm.md` |
|
|
179
|
+
| `ip-icon-count` | Compact inline indicator pairing a slotted icon with a value, e.g. an attachment count or a sensor reading | `docs/web-components/ip-icon-count/llm.md` |
|
|
180
|
+
| `ip-chip` | Presentational status/tag chip with orthogonal fill and border, a leading icon, a collapsed state, and a remove button | `docs/web-components/ip-chip/llm.md` |
|
|
181
|
+
| `ip-chip-group` | Groups `ip-chip` children as split buttons with one model: display, single, or multiple selection, plus per-chip removable, with focus restoration on keyboard removal | `docs/web-components/ip-chip-group/llm.md` |
|
|
182
|
+
| `ip-date-display` | Presentational date display with selectable detail, optional time, a `variant` for neutral emphasis or a semantic colour, and an optional leading icon slot; locale read reactively from `PixelLocaleService` | `docs/web-components/ip-date-display/llm.md` |
|
|
183
|
+
| `ip-main-menu` | Sidebar navigation wrapper with expanded/auto-hide/collapsed desktop modes and mobile drawer | `docs/web-components/ip-main-menu/llm.md` |
|
|
184
|
+
| `ip-main-menu-toggle` | Hamburger button for the top bar that opens the `ip-main-menu` mobile drawer via a shared store | `docs/web-components/ip-main-menu-toggle/llm.md` |
|
|
185
|
+
| `ip-main-menu-section` | Semantic section wrapper that groups navigation items with an optional visible label | `docs/web-components/ip-main-menu-section/llm.md` |
|
|
186
|
+
| `ip-main-menu-group` | Collapsible group of navigation items with label, icon, and animated chevron | `docs/web-components/ip-main-menu-group/llm.md` |
|
|
187
|
+
| `ip-main-menu-item` | Individual navigation item; renders as `<a>` when `href` is provided, otherwise as `<button>` | `docs/web-components/ip-main-menu-item/llm.md` |
|
|
187
188
|
|
|
188
189
|
## Services
|
|
189
190
|
|
|
190
|
-
| Service
|
|
191
|
-
|
|
|
192
|
-
| `PixelThemeService`
|
|
193
|
-
| `PixelI18nService`
|
|
191
|
+
| Service | Description | Docs |
|
|
192
|
+
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
|
|
193
|
+
| `PixelThemeService` | Static service for managing light/dark theme. Persists choice in localStorage | `docs/services/theme-service/llm.md` |
|
|
194
|
+
| `PixelI18nService` | Static i18n service for translating built-in component strings. Supports built-in languages and custom language injection | `docs/web-components/services/i18n/llm.md` |
|
|
195
|
+
| `PixelLocaleService` | Static service holding the active formatting locale for `Intl`-based components (dates now; numbers, currency later). Reactive, decoupled from i18n | `docs/web-components/services/locale/llm.md` |
|
|
194
196
|
|
|
195
197
|
## Migration guides
|
|
196
198
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { JSX } from '../../stencil-public-runtime';
|
|
2
|
+
import './i18n';
|
|
3
|
+
/** Presentational date display. Formats an ISO date via `Intl` using the reactive locale, with selectable detail, a `variant` that sets the text colour, and an optional leading icon slot. Not interactive. */
|
|
4
|
+
export declare class IpDateDisplay {
|
|
5
|
+
/** The date to display, as an ISO 8601 date (`2025-08-19`) or datetime (`2025-08-19T14:30`). Formatted internally. */
|
|
6
|
+
date: string;
|
|
7
|
+
/** Date detail level. Maps to the `Intl.DateTimeFormat` `dateStyle` option. */
|
|
8
|
+
dateFormat: 'short' | 'medium' | 'long';
|
|
9
|
+
/** Whether and how detailed the time is shown. Maps to `Intl.DateTimeFormat` `timeStyle`; `'none'` shows no time. Only applies when `date` carries a time component. */
|
|
10
|
+
timeFormat: 'none' | 'short' | 'medium';
|
|
11
|
+
/** Visual treatment. `primary`/`secondary`/`tertiary` are neutral emphasis levels; `success`/`warning`/`error` colour the date. The slotted icon inherits this colour. Set `label` to convey a semantic variant's meaning to assistive tech. */
|
|
12
|
+
variant: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'error';
|
|
13
|
+
/** Optional accessible label describing what a semantic variant means, e.g. "Overdue" or "Do not start before". Rendered as visually hidden text, since colour alone is not conveyed to assistive tech. */
|
|
14
|
+
label: string;
|
|
15
|
+
/** True when the `date` value carries a time component, so `timeFormat` and the local timezone apply. */
|
|
16
|
+
private get hasTimeComponent();
|
|
17
|
+
/** Formats `date` for display using the reactive locale. Date-only values are formatted in UTC to avoid a timezone-shifted midnight. */
|
|
18
|
+
private get formattedDate();
|
|
19
|
+
/** Builds the `Intl.DateTimeFormat` options from the format props and whether a time component is present. */
|
|
20
|
+
private get formatOptions();
|
|
21
|
+
/** Localized fallback shown when `date` is set but cannot be parsed. */
|
|
22
|
+
private get invalidLabel();
|
|
23
|
+
/** Renders a localized fallback for an unparseable date, without a dot or a `<time>` element. */
|
|
24
|
+
private renderInvalid;
|
|
25
|
+
/** Renders the formatted date inside a `<time>` element, with an optional decorative leading icon and an optional visually hidden label. */
|
|
26
|
+
private renderDate;
|
|
27
|
+
/** Chooses what to render: nothing for an empty date, a localized fallback for an invalid one, otherwise the formatted date. */
|
|
28
|
+
render(): JSX.Element;
|
|
29
|
+
}
|
|
@@ -329,6 +329,36 @@ export namespace Components {
|
|
|
329
329
|
*/
|
|
330
330
|
"value": string | string[] | undefined;
|
|
331
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* Presentational date display. Formats an ISO date via `Intl` using the reactive locale, with selectable detail, a `variant` that sets the text colour, and an optional leading icon slot. Not interactive.
|
|
334
|
+
*/
|
|
335
|
+
interface IpDateDisplay {
|
|
336
|
+
/**
|
|
337
|
+
* The date to display, as an ISO 8601 date (`2025-08-19`) or datetime (`2025-08-19T14:30`). Formatted internally.
|
|
338
|
+
* @default ''
|
|
339
|
+
*/
|
|
340
|
+
"date": string;
|
|
341
|
+
/**
|
|
342
|
+
* Date detail level. Maps to the `Intl.DateTimeFormat` `dateStyle` option.
|
|
343
|
+
* @default 'short'
|
|
344
|
+
*/
|
|
345
|
+
"dateFormat": 'short' | 'medium' | 'long';
|
|
346
|
+
/**
|
|
347
|
+
* Optional accessible label describing what a semantic variant means, e.g. "Overdue" or "Do not start before". Rendered as visually hidden text, since colour alone is not conveyed to assistive tech.
|
|
348
|
+
* @default ''
|
|
349
|
+
*/
|
|
350
|
+
"label": string;
|
|
351
|
+
/**
|
|
352
|
+
* Whether and how detailed the time is shown. Maps to `Intl.DateTimeFormat` `timeStyle`; `'none'` shows no time. Only applies when `date` carries a time component.
|
|
353
|
+
* @default 'none'
|
|
354
|
+
*/
|
|
355
|
+
"timeFormat": 'none' | 'short' | 'medium';
|
|
356
|
+
/**
|
|
357
|
+
* Visual treatment. `primary`/`secondary`/`tertiary` are neutral emphasis levels; `success`/`warning`/`error` colour the date. The slotted icon inherits this colour. Set `label` to convey a semantic variant's meaning to assistive tech.
|
|
358
|
+
* @default 'primary'
|
|
359
|
+
*/
|
|
360
|
+
"variant": 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'error';
|
|
361
|
+
}
|
|
332
362
|
/**
|
|
333
363
|
* Circular icon-only button with tooltip, five variants, three sizes, and form participation.
|
|
334
364
|
*/
|
|
@@ -687,6 +717,15 @@ declare global {
|
|
|
687
717
|
prototype: HTMLIpChipGroupElement;
|
|
688
718
|
new (): HTMLIpChipGroupElement;
|
|
689
719
|
};
|
|
720
|
+
/**
|
|
721
|
+
* Presentational date display. Formats an ISO date via `Intl` using the reactive locale, with selectable detail, a `variant` that sets the text colour, and an optional leading icon slot. Not interactive.
|
|
722
|
+
*/
|
|
723
|
+
interface HTMLIpDateDisplayElement extends Components.IpDateDisplay, HTMLStencilElement {
|
|
724
|
+
}
|
|
725
|
+
var HTMLIpDateDisplayElement: {
|
|
726
|
+
prototype: HTMLIpDateDisplayElement;
|
|
727
|
+
new (): HTMLIpDateDisplayElement;
|
|
728
|
+
};
|
|
690
729
|
/**
|
|
691
730
|
* Circular icon-only button with tooltip, five variants, three sizes, and form participation.
|
|
692
731
|
*/
|
|
@@ -798,6 +837,7 @@ declare global {
|
|
|
798
837
|
"ip-button": HTMLIpButtonElement;
|
|
799
838
|
"ip-chip": HTMLIpChipElement;
|
|
800
839
|
"ip-chip-group": HTMLIpChipGroupElement;
|
|
840
|
+
"ip-date-display": HTMLIpDateDisplayElement;
|
|
801
841
|
"ip-icon-button": HTMLIpIconButtonElement;
|
|
802
842
|
"ip-icon-count": HTMLIpIconCountElement;
|
|
803
843
|
"ip-main-menu": HTMLIpMainMenuElement;
|
|
@@ -1156,6 +1196,36 @@ declare namespace LocalJSX {
|
|
|
1156
1196
|
*/
|
|
1157
1197
|
"value"?: string | string[] | undefined;
|
|
1158
1198
|
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Presentational date display. Formats an ISO date via `Intl` using the reactive locale, with selectable detail, a `variant` that sets the text colour, and an optional leading icon slot. Not interactive.
|
|
1201
|
+
*/
|
|
1202
|
+
interface IpDateDisplay {
|
|
1203
|
+
/**
|
|
1204
|
+
* The date to display, as an ISO 8601 date (`2025-08-19`) or datetime (`2025-08-19T14:30`). Formatted internally.
|
|
1205
|
+
* @default ''
|
|
1206
|
+
*/
|
|
1207
|
+
"date"?: string;
|
|
1208
|
+
/**
|
|
1209
|
+
* Date detail level. Maps to the `Intl.DateTimeFormat` `dateStyle` option.
|
|
1210
|
+
* @default 'short'
|
|
1211
|
+
*/
|
|
1212
|
+
"dateFormat"?: 'short' | 'medium' | 'long';
|
|
1213
|
+
/**
|
|
1214
|
+
* Optional accessible label describing what a semantic variant means, e.g. "Overdue" or "Do not start before". Rendered as visually hidden text, since colour alone is not conveyed to assistive tech.
|
|
1215
|
+
* @default ''
|
|
1216
|
+
*/
|
|
1217
|
+
"label"?: string;
|
|
1218
|
+
/**
|
|
1219
|
+
* Whether and how detailed the time is shown. Maps to `Intl.DateTimeFormat` `timeStyle`; `'none'` shows no time. Only applies when `date` carries a time component.
|
|
1220
|
+
* @default 'none'
|
|
1221
|
+
*/
|
|
1222
|
+
"timeFormat"?: 'none' | 'short' | 'medium';
|
|
1223
|
+
/**
|
|
1224
|
+
* Visual treatment. `primary`/`secondary`/`tertiary` are neutral emphasis levels; `success`/`warning`/`error` colour the date. The slotted icon inherits this colour. Set `label` to convey a semantic variant's meaning to assistive tech.
|
|
1225
|
+
* @default 'primary'
|
|
1226
|
+
*/
|
|
1227
|
+
"variant"?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'error';
|
|
1228
|
+
}
|
|
1159
1229
|
/**
|
|
1160
1230
|
* Circular icon-only button with tooltip, five variants, three sizes, and form participation.
|
|
1161
1231
|
*/
|
|
@@ -1499,6 +1569,13 @@ declare namespace LocalJSX {
|
|
|
1499
1569
|
"orientation": 'horizontal' | 'vertical';
|
|
1500
1570
|
"disabled": boolean;
|
|
1501
1571
|
}
|
|
1572
|
+
interface IpDateDisplayAttributes {
|
|
1573
|
+
"date": string;
|
|
1574
|
+
"dateFormat": 'short' | 'medium' | 'long';
|
|
1575
|
+
"timeFormat": 'none' | 'short' | 'medium';
|
|
1576
|
+
"variant": 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'error';
|
|
1577
|
+
"label": string;
|
|
1578
|
+
}
|
|
1502
1579
|
interface IpIconButtonAttributes {
|
|
1503
1580
|
"variant": 'primary' | 'secondary' | 'tertiary' | 'brand' | 'destructive' | 'transparentOnLight' | 'transparentOnDark';
|
|
1504
1581
|
"size": 'small' | 'medium' | 'large';
|
|
@@ -1564,6 +1641,7 @@ declare namespace LocalJSX {
|
|
|
1564
1641
|
"ip-button": Omit<IpButton, keyof IpButtonAttributes> & { [K in keyof IpButton & keyof IpButtonAttributes]?: IpButton[K] } & { [K in keyof IpButton & keyof IpButtonAttributes as `attr:${K}`]?: IpButtonAttributes[K] } & { [K in keyof IpButton & keyof IpButtonAttributes as `prop:${K}`]?: IpButton[K] };
|
|
1565
1642
|
"ip-chip": Omit<IpChip, keyof IpChipAttributes> & { [K in keyof IpChip & keyof IpChipAttributes]?: IpChip[K] } & { [K in keyof IpChip & keyof IpChipAttributes as `attr:${K}`]?: IpChipAttributes[K] } & { [K in keyof IpChip & keyof IpChipAttributes as `prop:${K}`]?: IpChip[K] };
|
|
1566
1643
|
"ip-chip-group": Omit<IpChipGroup, keyof IpChipGroupAttributes> & { [K in keyof IpChipGroup & keyof IpChipGroupAttributes]?: IpChipGroup[K] } & { [K in keyof IpChipGroup & keyof IpChipGroupAttributes as `attr:${K}`]?: IpChipGroupAttributes[K] } & { [K in keyof IpChipGroup & keyof IpChipGroupAttributes as `prop:${K}`]?: IpChipGroup[K] };
|
|
1644
|
+
"ip-date-display": Omit<IpDateDisplay, keyof IpDateDisplayAttributes> & { [K in keyof IpDateDisplay & keyof IpDateDisplayAttributes]?: IpDateDisplay[K] } & { [K in keyof IpDateDisplay & keyof IpDateDisplayAttributes as `attr:${K}`]?: IpDateDisplayAttributes[K] } & { [K in keyof IpDateDisplay & keyof IpDateDisplayAttributes as `prop:${K}`]?: IpDateDisplay[K] };
|
|
1567
1645
|
"ip-icon-button": Omit<IpIconButton, keyof IpIconButtonAttributes> & { [K in keyof IpIconButton & keyof IpIconButtonAttributes]?: IpIconButton[K] } & { [K in keyof IpIconButton & keyof IpIconButtonAttributes as `attr:${K}`]?: IpIconButtonAttributes[K] } & { [K in keyof IpIconButton & keyof IpIconButtonAttributes as `prop:${K}`]?: IpIconButton[K] };
|
|
1568
1646
|
"ip-icon-count": Omit<IpIconCount, keyof IpIconCountAttributes> & { [K in keyof IpIconCount & keyof IpIconCountAttributes]?: IpIconCount[K] } & { [K in keyof IpIconCount & keyof IpIconCountAttributes as `attr:${K}`]?: IpIconCountAttributes[K] } & { [K in keyof IpIconCount & keyof IpIconCountAttributes as `prop:${K}`]?: IpIconCount[K] };
|
|
1569
1647
|
"ip-main-menu": Omit<IpMainMenu, keyof IpMainMenuAttributes> & { [K in keyof IpMainMenu & keyof IpMainMenuAttributes]?: IpMainMenu[K] } & { [K in keyof IpMainMenu & keyof IpMainMenuAttributes as `attr:${K}`]?: IpMainMenuAttributes[K] } & { [K in keyof IpMainMenu & keyof IpMainMenuAttributes as `prop:${K}`]?: IpMainMenu[K] } & OneOf<"heading", IpMainMenu["heading"], IpMainMenuAttributes["heading"]>;
|
|
@@ -1595,6 +1673,10 @@ declare module "@stencil/core" {
|
|
|
1595
1673
|
* controlled when `value` is bound.
|
|
1596
1674
|
*/
|
|
1597
1675
|
"ip-chip-group": LocalJSX.IntrinsicElements["ip-chip-group"] & JSXBase.HTMLAttributes<HTMLIpChipGroupElement>;
|
|
1676
|
+
/**
|
|
1677
|
+
* Presentational date display. Formats an ISO date via `Intl` using the reactive locale, with selectable detail, a `variant` that sets the text colour, and an optional leading icon slot. Not interactive.
|
|
1678
|
+
*/
|
|
1679
|
+
"ip-date-display": LocalJSX.IntrinsicElements["ip-date-display"] & JSXBase.HTMLAttributes<HTMLIpDateDisplayElement>;
|
|
1598
1680
|
/**
|
|
1599
1681
|
* Circular icon-only button with tooltip, five variants, three sizes, and form participation.
|
|
1600
1682
|
*/
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { IpButton } from './components/ip-button/ip-button';
|
|
2
2
|
export { PixelI18nService } from './services/i18n/i18n';
|
|
3
3
|
export type { PixelI18nConfig, PixelLanguage } from './services/i18n/i18n';
|
|
4
|
+
export { PixelLocaleService } from './services/locale/locale';
|
|
4
5
|
export type { MainMenuI18n } from './components/ip-main-menu/i18n';
|
|
5
6
|
export type { MainMenuToggleI18n } from './components/ip-main-menu-toggle/i18n';
|
|
6
7
|
export { IpMainMenu } from './components/ip-main-menu/ip-main-menu';
|
|
@@ -15,3 +16,5 @@ export { IpAvatarStack } from './components/ip-avatar-stack/ip-avatar-stack';
|
|
|
15
16
|
export { IpIconCount } from './components/ip-icon-count/ip-icon-count';
|
|
16
17
|
export { IpChip } from './components/ip-chip/ip-chip';
|
|
17
18
|
export { IpChipGroup } from './components/ip-chip-group/ip-chip-group';
|
|
19
|
+
export { IpDateDisplay } from './components/ip-date-display/ip-date-display';
|
|
20
|
+
export type { DateDisplayI18n } from './components/ip-date-display/i18n';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MainMenuI18n } from '../../components/ip-main-menu/i18n';
|
|
2
2
|
import type { MainMenuToggleI18n } from '../../components/ip-main-menu-toggle/i18n';
|
|
3
|
+
import type { DateDisplayI18n } from '../../components/ip-date-display/i18n';
|
|
3
4
|
/** Built-in language codes supported out of the box. */
|
|
4
5
|
export type PixelLanguage = 'en' | 'nb-NO';
|
|
5
6
|
/**
|
|
@@ -14,6 +15,8 @@ export interface PixelI18nConfig {
|
|
|
14
15
|
ipMainMenu?: Partial<MainMenuI18n>;
|
|
15
16
|
'ip-main-menu-toggle'?: Partial<MainMenuToggleI18n>;
|
|
16
17
|
ipMainMenuToggle?: Partial<MainMenuToggleI18n>;
|
|
18
|
+
'ip-date-display'?: Partial<DateDisplayI18n>;
|
|
19
|
+
ipDateDisplay?: Partial<DateDisplayI18n>;
|
|
17
20
|
}
|
|
18
21
|
/** Internal translation store and lookup. Not re-exported from the package root. */
|
|
19
22
|
export declare class PixelTranslationService {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { PixelI18nService } from './i18n/i18n';
|
|
2
2
|
export type { PixelI18nConfig, PixelLanguage } from './i18n/i18n';
|
|
3
3
|
export type { MainMenuI18n } from '../components/ip-main-menu/i18n';
|
|
4
|
+
export type { DateDisplayI18n } from '../components/ip-date-display/i18n';
|
|
5
|
+
export { PixelLocaleService } from './locale/locale';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consumer-facing locale API. Holds the app's active locale for formatting (dates now;
|
|
3
|
+
* numbers, currency, relative time later). Calling {@link setLocale} re-renders all mounted
|
|
4
|
+
* Stencil components that read the locale in render().
|
|
5
|
+
*/
|
|
6
|
+
export declare class PixelLocaleService {
|
|
7
|
+
/**
|
|
8
|
+
* Sets the active formatting locale. Triggers a re-render of all components using the locale.
|
|
9
|
+
* @param locale - A BCP 47 language tag (e.g. `'nb-NO'`, `'en-US'`). Use {@link resetLocale} to follow the runtime/browser locale instead.
|
|
10
|
+
*/
|
|
11
|
+
static setLocale(locale: string): void;
|
|
12
|
+
/**
|
|
13
|
+
* Clears the active locale so formatting follows the runtime/browser locale again.
|
|
14
|
+
* Triggers a re-render of all components using the locale.
|
|
15
|
+
*/
|
|
16
|
+
static resetLocale(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Returns the current formatting locale. Reading localeState.locale here enables @stencil/store
|
|
19
|
+
* auto-tracking, so components calling this inside render() re-render on {@link setLocale}.
|
|
20
|
+
* @returns The active BCP 47 locale, or `undefined` when following the environment.
|
|
21
|
+
*/
|
|
22
|
+
static getLocale(): string | undefined;
|
|
23
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{g as getAssetPath,r as render,s as setAssetPath,a as setNonce,b as setPlatformOptions}from"./p-D83crOsE.js";export{I as IpButton}from"./p-DVwQwKni.js";export{P as PixelI18nService}from"./p-
|
|
1
|
+
export{g as getAssetPath,r as render,s as setAssetPath,a as setNonce,b as setPlatformOptions}from"./p-D83crOsE.js";export{I as IpButton}from"./p-DVwQwKni.js";export{P as PixelI18nService}from"./p-B7OyzFE9.js";export{I as IpDateDisplay,P as PixelLocaleService}from"./p-CFwDQCcr.js";export{I as IpMainMenu}from"./p-6Y3JP5Mp.js";export{I as IpMainMenuToggle}from"./p-npk6jupt.js";export{I as IpMainMenuSection}from"./p-FtNC-zkT.js";export{I as IpMainMenuGroup}from"./p-DvqClY_a.js";export{I as IpMainMenuItem}from"./p-8xxrpIeZ.js";export{I as IpIconButton}from"./p-DTh1Kvjd.js";export{I as IpTooltip}from"./p-VctHpAA_.js";export{I as IpAvatar}from"./p-ntoTViAh.js";export{I as IpAvatarStack}from"./p-BPNcFvV4.js";export{I as IpIconCount}from"./p-U-7IBVRB.js";export{I as IpChip}from"./p-BG9BklGR.js";export{I as IpChipGroup}from"./p-CU3XMYRk.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Components, JSX } from "../../types/components";
|
|
2
|
+
|
|
3
|
+
interface IpDateDisplay extends Components.IpDateDisplay, HTMLElement {}
|
|
4
|
+
export const IpDateDisplay: {
|
|
5
|
+
prototype: IpDateDisplay;
|
|
6
|
+
new (): IpDateDisplay;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Used to define this component and all nested components recursively.
|
|
10
|
+
*/
|
|
11
|
+
export const defineCustomElement: () => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{I as o,d as r}from"./p-CFwDQCcr.js";const s=o,p=r;export{s as IpDateDisplay,p as defineCustomElement}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{I as o,d as s}from"./p-
|
|
1
|
+
import{I as o,d as s}from"./p-DvqClY_a.js";const a=o,p=s;export{a as IpMainMenuGroup,p as defineCustomElement}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{I as o,d as
|
|
1
|
+
import{I as o,d as p}from"./p-8xxrpIeZ.js";const r=o,s=p;export{r as IpMainMenuItem,s as defineCustomElement}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{I as o,d as s}from"./p-
|
|
1
|
+
import{I as o,d as s}from"./p-FtNC-zkT.js";const t=o,p=s;export{t as IpMainMenuSection,p as defineCustomElement}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{I as
|
|
1
|
+
import{I as p,d as o}from"./p-npk6jupt.js";const s=p,t=o;export{s as IpMainMenuToggle,t as defineCustomElement}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{I as o,d as
|
|
1
|
+
import{I as o,d as p}from"./p-6Y3JP5Mp.js";const s=o,r=p;export{s as IpMainMenu,r as defineCustomElement}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as i,p as n,H as e,c as a,h as t,d as o}from"./p-D83crOsE.js";import{a as s}from"./p-B7OyzFE9.js";import{d as m,e as p,f as r,g as l}from"./p-C7Xl2j2X.js";import{m as c}from"./p-DefPpKsB.js";import{M as d}from"./p-DnTzptWz.js";import{d as u}from"./p-DTh1Kvjd.js";import{d as h}from"./p-VctHpAA_.js";s.registerComponent("ip-main-menu",{en:{collapseMenu:"Collapse menu",expandMenu:"Expand menu",pinMenu:"Pin menu",unpinMenu:"Unpin menu",closeMenu:"Close menu"},"nb-NO":{collapseMenu:"Skjul meny",expandMenu:"Vis meny",pinMenu:"Fest menyen",unpinMenu:"Løsne menyen",closeMenu:"Lukk meny"}});const b=n(class extends e{constructor(i){super(),!1!==i&&this.__registerHost(),this.__attachShadow(),this.ipModeChange=a(this,"ipModeChange",7),this.ipMobileOpenChange=a(this,"ipMobileOpenChange",7),this.ipBrandClick=a(this,"ipBrandClick",7),this.mode="expanded",this.expandDelay=300,this.collapseDelay=300,this.mobileBreakpoint="1024px",this.isHoverExpanded=!1,this.handleDocumentKeydown=i=>{"Escape"===i.key&&d.setMobileOpen(!1)},this.handleHoverZoneEnter=()=>{"auto-hide"===d.mode&&(this.clearHoverCollapseTimer(),this.isHoverExpanded||(this.clearHoverExpandTimer(),this.hoverExpandTimer=setTimeout((()=>{this.isHoverExpanded=!0,this.hoverExpandTimer=void 0}),this.expandDelay)))},this.handleHoverZoneLeave=()=>{this.clearHoverExpandTimer(),this.isHoverExpanded&&this.startCollapseTimer()},this.startCollapseTimer=()=>{this.clearHoverCollapseTimer(),this.hoverCollapseTimer=setTimeout((()=>{this.hasKeyboardFocusWithin()||(this.isHoverExpanded=!1),this.hoverCollapseTimer=void 0}),this.collapseDelay)},this.hasKeyboardFocusWithin=()=>{let i=document.activeElement;if(!i||!this.el.contains(i))return!1;for(;i.shadowRoot?.activeElement;)i=i.shadowRoot.activeElement;return i.matches(":focus-visible")},this.handleNavFocusIn=()=>{"auto-hide"===d.mode&&(this.clearHoverCollapseTimer(),this.isHoverExpanded||(this.clearHoverExpandTimer(),this.isHoverExpanded=!0))},this.handleNavFocusOut=i=>{const n=i.relatedTarget;d.isMobileOpen?n&&!this.containsFocusTarget(n)&&this.focusCloseButton():this.isHoverExpanded&&(this.containsFocusTarget(n)||this.startCollapseTimer())},this.clearHoverExpandTimer=()=>{void 0!==this.hoverExpandTimer&&(clearTimeout(this.hoverExpandTimer),this.hoverExpandTimer=void 0)},this.clearHoverCollapseTimer=()=>{void 0!==this.hoverCollapseTimer&&(clearTimeout(this.hoverCollapseTimer),this.hoverCollapseTimer=void 0)},this.clearHoverTimers=()=>{this.clearHoverExpandTimer(),this.clearHoverCollapseTimer()},this.handlePinClick=()=>{this.applyUserMode("auto-hide"===d.mode?"expanded":"auto-hide")},this.handleCollapseClick=()=>{this.applyUserMode("expanded"===d.mode?"collapsed":"expanded")},this.handleCloseClick=()=>{d.setMobileOpen(!1)},this.handleBrandClick=()=>{this.ipBrandClick.emit()}}componentWillLoad(){d.isModeUserOverridden?this.mode=d.mode:d.setMode(this.mode),d.setMobileBreakpoint(this.mobileBreakpoint)}connectedCallback(){this.unsubscribeMobileOpen=d.onMobileOpenChange((i=>{this.ipMobileOpenChange.emit(i),this.handleMobileOpenChanged(i)}))}disconnectedCallback(){this.unsubscribeMobileOpen?.(),this.clearHoverTimers(),document.removeEventListener("keydown",this.handleDocumentKeydown)}handleMobileOpenChanged(i){i?(document.addEventListener("keydown",this.handleDocumentKeydown),requestAnimationFrame((()=>this.focusCloseButton()))):document.removeEventListener("keydown",this.handleDocumentKeydown)}focusCloseButton(){this.closeButton?.focus()}containsFocusTarget(i){return!!i&&(this.el.contains(i)||(this.el.shadowRoot?.contains(i)??!1))}onModeChange(i){d.setMode(i),this.clearHoverTimers(),this.isHoverExpanded=!1}syncBreakpoint(){d.setMobileBreakpoint(this.mobileBreakpoint)}applyUserMode(i){d.setModeFromUser(i),this.mode=i,this.ipModeChange.emit(i)}renderBrand(){const i=t("slot",{name:"logo"},t("span",{class:"ip-main-menu__isy-logo","aria-label":"ISY",innerHTML:m})),n=t("span",{class:"ip-main-menu__heading"},this.heading);return this.brandHref?t("a",{href:this.brandHref,class:"ip-main-menu__brand","aria-label":this.heading},i,n):t("button",{type:"button",class:"ip-main-menu__brand","aria-label":this.heading,onClick:this.handleBrandClick},i,n)}render(){const i=d.mode,n="expanded"!==i,e=d.isMobileOpen,a="auto-hide"===i&&this.isHoverExpanded?"":void 0,m=c(this.mobileBreakpoint,"\n .ip-main-menu__backdrop--visible { --ip-main-menu-backdrop-display: block; }\n\n .ip-main-menu__nav {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 100;\n transform: translateX(-100%);\n visibility: hidden;\n --ip-main-menu-nav-width: 260px;\n --ip-main-menu-nav-height: 100svh;\n --ip-main-menu-nav-transition: transform 0.3s ease, visibility 0s linear 0.3s;\n }\n\n .ip-main-menu__nav--mobile-open {\n transform: translateX(0);\n visibility: visible;\n --ip-main-menu-nav-transition: transform 0.3s ease, visibility 0s linear 0s;\n --ip-main-menu-label-display: block;\n --ip-main-menu-icon-justify: flex-start;\n --ip-main-menu-chevron-position: static;\n --ip-main-menu-chevron-margin: auto;\n --ip-main-menu-chevron-right: auto;\n --ip-main-menu-chevron-top: auto;\n --ip-main-menu-chevron-bottom: auto;\n --ip-main-menu-logo-display: none;\n --ip-main-menu-heading-display: block;\n --ip-main-menu-chevron-icon-size: var(--ip_iconography_size_tiny);\n --ip-main-menu-item-icon-size: var(--ip_iconography_size_small);\n --ip-main-menu-section-label-text-visibility: visible;\n --ip-main-menu-section-indicator-display: none;\n }\n\n .ip-main-menu__desktop-controls { --ip-main-menu-desktop-controls-display: none; }\n .ip-main-menu__mobile-close { --ip-main-menu-mobile-close-display: inline-flex; }\n .ip-main-menu__brand { --ip-main-menu-brand-flex: 1; }\n\n @media (max-width: 767px) {\n .ip-main-menu__nav { --ip-main-menu-nav-width: 100%; }\n }\n");return t(o,{key:"01638d7344b50bdf5a45742c82b79eaa27cebf20","data-mode":i,"data-hover-expanded":a},t("style",{key:"9468bafb82e55b409268d66aaf57924552ede840"},m),t("div",{key:"81729d10360ef4b7321ea7fdbda56bff35992f79",class:"ip-main-menu__backdrop"+(e?" ip-main-menu__backdrop--visible":""),"aria-hidden":"true",onClick:this.handleCloseClick}),t("nav",{key:"1f94084b572e22b0e6510892105ba8db92730624",class:"ip-main-menu__nav"+(e?" ip-main-menu__nav--mobile-open":""),"aria-label":this.heading,onFocusin:this.handleNavFocusIn,onFocusout:this.handleNavFocusOut},t("div",{key:"c7d0e39e80170f94f2af849bf6cafd1e03ded7e3",class:"ip-main-menu__header"},this.renderBrand(),t("ip-icon-button",{key:"0a56d0ec32c512d0fd0333271f6d3ea7a75776fa",class:"ip-main-menu__mobile-close",ref:i=>this.closeButton=i,variant:"transparentOnDark",size:"large",tooltipSize:"medium",tooltipPosition:"right",tooltipVariant:"onDark",label:s.translate("ip-main-menu","closeMenu"),onClick:this.handleCloseClick},t("slot",{key:"2d2237bf8b78ec1558eba27d65cffacf75094cb4",name:"icon-close",slot:"icon"},t("span",{key:"388cbece4efc9a281dffdd8fba60b81aa1b066dc",class:"ip-main-menu__icon","aria-hidden":"true",innerHTML:p})))),t("div",{key:"1db8fd183115977bb0c7ecb129e7835c608c1df2",class:"ip-main-menu__desktop-controls"},"auto-hide"!==i&&t("ip-icon-button",{key:"e6e0535108797974c8cf2346f2f970b5f409c7e6",class:"ip-main-menu__collapse-btn",variant:"transparentOnDark",size:"large",tooltipSize:"medium",tooltipVariant:"onDark",tooltipHideOnClick:!1,label:s.translate("ip-main-menu",n?"expandMenu":"collapseMenu"),onClick:this.handleCollapseClick},t("slot",{key:"0b5e73c78d28ffe3edc04a4a79a2685fd783f0c2",name:"icon-collapse",slot:"icon"},t("span",{key:"093c09997830c8f099d2290b0e36696729cb882e",class:"ip-main-menu__icon","aria-hidden":"true",innerHTML:r}))),"collapsed"!==i&&t("ip-icon-button",{key:"6205078e42da39744581ab753a2ffefd5286b4a0",class:"ip-main-menu__pin-btn",variant:"transparentOnDark",size:"large",tooltipSize:"medium",tooltipVariant:"onDark",tooltipHideOnClick:!1,label:s.translate("ip-main-menu","auto-hide"===i?"pinMenu":"unpinMenu"),onClick:this.handlePinClick},"auto-hide"===i?t("slot",{name:"icon-unpin",slot:"icon"},t("span",{class:"ip-main-menu__icon ip-main-menu__icon--unpin","aria-hidden":"true",innerHTML:l})):t("slot",{name:"icon-pin",slot:"icon"},t("span",{class:"ip-main-menu__icon","aria-hidden":"true",innerHTML:l})))),t("div",{key:"08bc261a0939fb9d6cacb84a052449e49f38ebd2",class:"ip-main-menu__hover-zone",onMouseEnter:this.handleHoverZoneEnter,onMouseLeave:this.handleHoverZoneLeave},t("div",{key:"443a07f32485be8d8bb49bb81c17ccedad70e1b7",class:"ip-main-menu__items"},t("slot",{key:"91e5e89055985c1d8241000377e4004869a87527"})),t("div",{key:"4f93fdae66607c841009b4006196851c18a6caa1",class:"ip-main-menu__bottom"},t("slot",{key:"b34147231867d213f1606b14f0dcae20c167fc11",name:"bottom"})))))}get el(){return this}static get watchers(){return{mode:[{onModeChange:0}],mobileBreakpoint:[{syncBreakpoint:0}]}}static get style(){return":host{display:block;height:100%;position:relative;--ip-main-menu-width:230px;--ip-main-menu-label-display:block;--ip-main-menu-icon-justify:flex-start;--ip-main-menu-controls-justify:flex-end;--ip-main-menu-chevron-display:inline-flex;--ip-main-menu-chevron-position:static;--ip-main-menu-chevron-margin:auto;--ip-main-menu-chevron-right:auto;--ip-main-menu-chevron-top:auto;--ip-main-menu-chevron-bottom:auto;--ip-main-menu-logo-display:none;--ip-main-menu-heading-display:block;--ip-main-menu-chevron-icon-size:var(--ip_iconography_size_tiny);--ip-main-menu-item-icon-size:var(--ip_iconography_size_small);--ip-main-menu-collapse-icon-rotation:0deg;--ip-main-menu-section-label-padding-start:var(--ip_spacing_space_150)}:host([data-mode=auto-hide][data-hover-expanded]){--ip-main-menu-width:230px;--ip-main-menu-label-display:block;--ip-main-menu-icon-justify:flex-start;--ip-main-menu-controls-justify:flex-end;--ip-main-menu-chevron-display:inline-flex;--ip-main-menu-chevron-position:static;--ip-main-menu-chevron-margin:auto;--ip-main-menu-chevron-right:auto;--ip-main-menu-chevron-top:auto;--ip-main-menu-chevron-bottom:auto;--ip-main-menu-logo-display:none;--ip-main-menu-heading-display:block;--ip-main-menu-chevron-icon-size:var(--ip_iconography_size_tiny);--ip-main-menu-item-icon-size:var(--ip_iconography_size_small);--ip-main-menu-section-label-padding-start:var(--ip_spacing_space_150);--ip-main-menu-brand-flex:0 0 auto;--ip-main-menu-brand-justify:flex-start}:host([data-mode=collapsed]) .ip-main-menu__brand,:host([data-mode=auto-hide]) .ip-main-menu__brand{overflow:visible}:host([data-mode=collapsed]){--ip-main-menu-collapse-icon-rotation:180deg}:host([data-mode=collapsed]),:host([data-mode=auto-hide]){--ip-main-menu-width:64px;--ip-main-menu-label-display:none;--ip-main-menu-icon-justify:center;--ip-main-menu-controls-justify:center;--ip-main-menu-chevron-position:absolute;--ip-main-menu-chevron-margin:0;--ip-main-menu-chevron-right:4px;--ip-main-menu-chevron-top:0;--ip-main-menu-chevron-bottom:0;--ip-main-menu-logo-display:inline-flex;--ip-main-menu-heading-display:none;--ip-main-menu-chevron-icon-size:8px;--ip-main-menu-item-icon-size:var(--ip_iconography_size_tiny);--ip-main-menu-section-label-padding-start:calc(50% - 10px);--ip-main-menu-brand-flex:1;--ip-main-menu-brand-justify:center}.ip-main-menu__backdrop{display:var(--ip-main-menu-backdrop-display, none);position:fixed;inset:0;background-color:rgba(0, 0, 0, 0.5);z-index:99}.ip-main-menu__nav{display:flex;flex-direction:column;height:var(--ip-main-menu-nav-height, 100%);width:var(--ip-main-menu-nav-width, var(--ip-main-menu-width));max-width:100vw;background-color:var(--ip_color_menu_main_background_primary_default);overflow-y:auto;overflow-x:hidden;transition:var(--ip-main-menu-nav-transition, width 0.2s ease);flex-shrink:0}.ip-main-menu__nav::-webkit-scrollbar{width:4px}.ip-main-menu__nav::-webkit-scrollbar-track{background:transparent}.ip-main-menu__nav::-webkit-scrollbar-thumb{background-color:rgba(255, 255, 255, 0.25);border-radius:2px}.ip-main-menu__nav::-webkit-scrollbar-thumb:hover{background-color:rgba(255, 255, 255, 0.4)}@supports not selector(::-webkit-scrollbar){.ip-main-menu__nav{scrollbar-width:thin;scrollbar-color:rgba(255, 255, 255, 0.25) transparent}}.ip-main-menu__header{display:flex;align-items:center;width:100%;height:56px;flex-shrink:0}.ip-main-menu__brand{align-self:stretch;display:inline-flex;align-items:center;justify-content:var(--ip-main-menu-brand-justify, flex-start);flex:var(--ip-main-menu-brand-flex, 0 0 auto);min-width:0;overflow:hidden;padding:0;padding-inline:var(--ip_spacing_space_150);border:none;background:transparent;text-decoration:none;color:inherit;font:inherit;cursor:pointer}.ip-main-menu__brand:focus-visible{outline:2px solid var(--ip_color_button_focus_default);outline-offset:-2px}.ip-main-menu__heading{display:var(--ip-main-menu-heading-display, block);font-family:var(--ip_typography_font_family_tertiary);font-size:18px;font-weight:100;color:#ffffff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ip-main-menu__isy-logo{display:var(--ip-main-menu-logo-display, none);align-items:center;color:#ffffff}.ip-main-menu__desktop-controls{display:var(--ip-main-menu-desktop-controls-display, flex);align-items:center;justify-content:var(--ip-main-menu-controls-justify);gap:var(--ip_spacing_space_050);padding:4px 8px 24px;flex-shrink:0}.ip-main-menu__mobile-close{display:var(--ip-main-menu-mobile-close-display, none);margin-inline-start:auto;margin-inline-end:var(--ip_spacing_space_050)}.ip-main-menu__icon{display:inline-flex;align-items:center;justify-content:center}.ip-main-menu__icon svg{width:var(--ip_iconography_size_tiny);height:var(--ip_iconography_size_tiny)}.ip-main-menu__collapse-btn .ip-main-menu__icon{transform:rotate(var(--ip-main-menu-collapse-icon-rotation));transition:transform 0.2s ease}.ip-main-menu__icon--unpin{transform:rotate(45deg)}.ip-main-menu__hover-zone{display:flex;flex-direction:column;flex:1;min-height:0}.ip-main-menu__items{flex:1}.ip-main-menu__bottom{padding:0;flex-shrink:0}::slotted([slot=icon-collapse]){font-size:var(--ip_iconography_size_tiny) !important;transform:rotate(var(--ip-main-menu-collapse-icon-rotation)) !important;transition:transform 0.2s ease !important}::slotted([slot=icon-pin]),::slotted([slot=icon-unpin]),::slotted([slot=icon-hamburger]),::slotted([slot=icon-close]){font-size:var(--ip_iconography_size_tiny) !important}"}},[257,"ip-main-menu",{heading:[513],mode:[1537],brandHref:[513,"brand-href"],expandDelay:[514,"expand-delay"],collapseDelay:[514,"collapse-delay"],mobileBreakpoint:[513,"mobile-breakpoint"],isHoverExpanded:[32]},void 0,{mode:[{onModeChange:0}],mobileBreakpoint:[{syncBreakpoint:0}]}]);function _(){"undefined"!=typeof customElements&&["ip-main-menu","ip-icon-button","ip-tooltip"].forEach((n=>{switch(n){case"ip-main-menu":customElements.get(i(n))||customElements.define(i(n),b);break;case"ip-icon-button":customElements.get(i(n))||u();break;case"ip-tooltip":customElements.get(i(n))||h()}}))}_();export{b as I,_ as d}
|