@norconsult-digital-public/isypixel 2.0.1 → 2.0.2-canary.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/llm.md +4 -3
  2. package/dist/types/components/ip-button/ip-button.d.ts +7 -0
  3. package/dist/types/components/ip-tooltip/ip-tooltip.d.ts +48 -0
  4. package/dist/types/components.d.ts +127 -0
  5. package/dist/types/index.d.ts +1 -0
  6. package/dist/web-components/components/index.js +1 -1
  7. package/dist/web-components/components/ip-button/llm.md +17 -10
  8. package/dist/web-components/components/ip-button.js +1 -1
  9. package/dist/web-components/components/ip-tooltip/llm.md +151 -0
  10. package/dist/web-components/components/ip-tooltip.d.ts +11 -0
  11. package/dist/web-components/components/ip-tooltip.js +1 -0
  12. package/dist/web-components/components/p-BWyvzXuA.js +1 -0
  13. package/dist/web-components/components/p-CHBDz3Co.js +1 -0
  14. package/dist/web-components/components/p-CW9GjbMh.js +1 -0
  15. package/dist/web-components/generated/angular/components.d.ts +53 -2
  16. package/dist/web-components/generated/angular/components.js +80 -4
  17. package/dist/web-components/generated/angular/components.ts +71 -3
  18. package/dist/web-components/generated/angular/index.d.ts +1 -1
  19. package/dist/web-components/generated/angular/index.js +2 -1
  20. package/dist/web-components/generated/angular/index.ts +2 -1
  21. package/dist/web-components/generated/react/components.d.ts +8 -1
  22. package/dist/web-components/generated/react/components.js +12 -5
  23. package/dist/web-components/generated/react/components.ts +20 -1
  24. package/dist/web-components/generated/svelte/components.d.ts +2 -0
  25. package/dist/web-components/generated/vue/components.d.ts +1 -0
  26. package/dist/web-components/generated/vue/components.js +16 -0
  27. package/dist/web-components/generated/vue/components.ts +18 -0
  28. package/package.json +8 -2
package/dist/llm.md CHANGED
@@ -169,9 +169,10 @@ In `index.html` `<body>`:
169
169
 
170
170
  ## Components
171
171
 
172
- | Component | Description | Docs |
173
- | ----------- | ------------------------------------------------------------------- | -------------------------------------------- |
174
- | `ip-button` | Clickable button with visual variants, loading state, and icon slot | `web-components/components/ip-button/llm.md` |
172
+ | Component | Description | Docs |
173
+ | ------------ | ------------------------------------------------------------------------------------------ | --------------------------------------------- |
174
+ | `ip-button` | Clickable button with visual variants, loading state, and icon slot | `web-components/components/ip-button/llm.md` |
175
+ | `ip-tooltip` | Tooltip that wraps a trigger and shows non-interactive content on hover, focus, and Escape | `web-components/components/ip-tooltip/llm.md` |
175
176
 
176
177
  ## Services
177
178
 
@@ -1,6 +1,10 @@
1
1
  import { JSX } from '../../stencil-public-runtime';
2
2
  export declare class IpButton {
3
3
  internals: ElementInternals;
4
+ /** Accessible name forwarded to the inner <button>. Useful for icon-only usage, and when provided it overrides the accessible name derived from any slotted label text. */
5
+ ariaLabel: string | null;
6
+ /** Tracks whether the default slot has assigned content. Used to skip rendering the label `<span>` when the button is icon-only, preventing an unwanted flex gap. Set reactively via `onLabelSlotChange`. */
7
+ private hasLabel;
4
8
  /** Visual variant of the button */
5
9
  variant: 'primary' | 'secondary' | 'tertiary' | 'brand' | 'destructive';
6
10
  /** Shows a loading spinner and disables interaction */
@@ -13,6 +17,9 @@ export declare class IpButton {
13
17
  size: 'small' | 'medium' | 'large';
14
18
  /** Position of the icon slot — "start" places it before the label, "end" places it after */
15
19
  alignIcon: 'start' | 'end';
20
+ /** Fires on `slotchange` for the default slot. Updates `hasLabel` so the label `<span>` wrapper is only rendered when text content is present. */
21
+ private onLabelSlotChange;
22
+ /** Delegates form actions to the associated form element based on the `type` prop. The inner `<button>` always has `type="button"` to prevent default browser submit behaviour. */
16
23
  private handleClick;
17
24
  render(): JSX.Element;
18
25
  }
@@ -0,0 +1,48 @@
1
+ import { EventEmitter, JSX } from '../../stencil-public-runtime';
2
+ export declare class IpTooltip {
3
+ /** Placement of the tooltip bubble relative to the trigger element. */
4
+ position: 'top' | 'right' | 'bottom' | 'left';
5
+ /** Visual size of the tooltip bubble. */
6
+ size: 'small' | 'medium' | 'large';
7
+ /** Delay in milliseconds before the tooltip appears on hover. */
8
+ delay: number;
9
+ /** Forces the tooltip visible regardless of hover or focus state. */
10
+ visible: boolean;
11
+ /** Prevents the tooltip from showing on hover or focus. */
12
+ disabled: boolean;
13
+ /** Renders a directional arrow pointing toward the trigger element. */
14
+ arrow: boolean;
15
+ /** Maximum width of the tooltip bubble. Use absolute or viewport units — percentage values are not supported as they resolve relative to the trigger element. E.g. "300px", "20rem", "50vw". */
16
+ maxWidth: string;
17
+ /** Internal hover/focus activation state, independent of the `visible` prop. */
18
+ private isActive;
19
+ /** Emitted when the tooltip transitions from hidden to visible. */
20
+ tooltipShow: EventEmitter<void>;
21
+ /** Emitted when the tooltip transitions from visible to hidden. */
22
+ tooltipHide: EventEmitter<void>;
23
+ private readonly tooltipId;
24
+ private delayTimer;
25
+ private hideTimer;
26
+ /** Clears any pending show or hide timers. */
27
+ private clearTimers;
28
+ /** Updates isActive and emits show/hide when the final visibility state changes. */
29
+ private setActive;
30
+ /** Emits show/hide when the `visible` prop changes and the final state differs. */
31
+ onVisibleChange(newValue: boolean, oldValue: boolean): void;
32
+ /** Hides the tooltip immediately when the component is disabled while active. */
33
+ onDisabledChange(newValue: boolean): void;
34
+ disconnectedCallback(): void;
35
+ /** Whether the tooltip is currently displayed, combining `visible` and hover/focus state. */
36
+ private get isTooltipVisible();
37
+ private handleTriggerMouseEnter;
38
+ private handleTriggerMouseLeave;
39
+ private handleTooltipMouseEnter;
40
+ private handleTooltipMouseLeave;
41
+ /** Fires when any focusable child (including slotted trigger) receives focus. */
42
+ handleFocusin(): void;
43
+ /** Fires when focus leaves the component entirely. */
44
+ handleFocusout(): void;
45
+ /** Closes the tooltip on Escape as required by WCAG 1.4.13. Only clears hover/focus state — does not affect the `visible` prop. */
46
+ private handleKeyDown;
47
+ render(): JSX.Element;
48
+ }
@@ -12,6 +12,11 @@ export namespace Components {
12
12
  * @default 'start'
13
13
  */
14
14
  "alignIcon": 'start' | 'end';
15
+ /**
16
+ * Accessible name forwarded to the inner <button>. Useful for icon-only usage, and when provided it overrides the accessible name derived from any slotted label text.
17
+ * @default null
18
+ */
19
+ "ariaLabel": string | null;
15
20
  /**
16
21
  * Disables the button
17
22
  * @default false
@@ -38,6 +43,47 @@ export namespace Components {
38
43
  */
39
44
  "variant": 'primary' | 'secondary' | 'tertiary' | 'brand' | 'destructive';
40
45
  }
46
+ interface IpTooltip {
47
+ /**
48
+ * Renders a directional arrow pointing toward the trigger element.
49
+ * @default true
50
+ */
51
+ "arrow": boolean;
52
+ /**
53
+ * Delay in milliseconds before the tooltip appears on hover.
54
+ * @default 300
55
+ */
56
+ "delay": number;
57
+ /**
58
+ * Prevents the tooltip from showing on hover or focus.
59
+ * @default false
60
+ */
61
+ "disabled": boolean;
62
+ /**
63
+ * Maximum width of the tooltip bubble. Use absolute or viewport units — percentage values are not supported as they resolve relative to the trigger element. E.g. "300px", "20rem", "50vw".
64
+ * @default '300px'
65
+ */
66
+ "maxWidth": string;
67
+ /**
68
+ * Placement of the tooltip bubble relative to the trigger element.
69
+ * @default 'top'
70
+ */
71
+ "position": 'top' | 'right' | 'bottom' | 'left';
72
+ /**
73
+ * Visual size of the tooltip bubble.
74
+ * @default 'medium'
75
+ */
76
+ "size": 'small' | 'medium' | 'large';
77
+ /**
78
+ * Forces the tooltip visible regardless of hover or focus state.
79
+ * @default false
80
+ */
81
+ "visible": boolean;
82
+ }
83
+ }
84
+ export interface IpTooltipCustomEvent<T> extends CustomEvent<T> {
85
+ detail: T;
86
+ target: HTMLIpTooltipElement;
41
87
  }
42
88
  declare global {
43
89
  interface HTMLIpButtonElement extends Components.IpButton, HTMLStencilElement {
@@ -46,8 +92,27 @@ declare global {
46
92
  prototype: HTMLIpButtonElement;
47
93
  new (): HTMLIpButtonElement;
48
94
  };
95
+ interface HTMLIpTooltipElementEventMap {
96
+ "show": void;
97
+ "hide": void;
98
+ }
99
+ interface HTMLIpTooltipElement extends Components.IpTooltip, HTMLStencilElement {
100
+ addEventListener<K extends keyof HTMLIpTooltipElementEventMap>(type: K, listener: (this: HTMLIpTooltipElement, ev: IpTooltipCustomEvent<HTMLIpTooltipElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
101
+ addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
102
+ addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
103
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
104
+ removeEventListener<K extends keyof HTMLIpTooltipElementEventMap>(type: K, listener: (this: HTMLIpTooltipElement, ev: IpTooltipCustomEvent<HTMLIpTooltipElementEventMap[K]>) => any, options?: boolean | EventListenerOptions): void;
105
+ removeEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
106
+ removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
107
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
108
+ }
109
+ var HTMLIpTooltipElement: {
110
+ prototype: HTMLIpTooltipElement;
111
+ new (): HTMLIpTooltipElement;
112
+ };
49
113
  interface HTMLElementTagNameMap {
50
114
  "ip-button": HTMLIpButtonElement;
115
+ "ip-tooltip": HTMLIpTooltipElement;
51
116
  }
52
117
  }
53
118
  declare namespace LocalJSX {
@@ -57,6 +122,11 @@ declare namespace LocalJSX {
57
122
  * @default 'start'
58
123
  */
59
124
  "alignIcon"?: 'start' | 'end';
125
+ /**
126
+ * Accessible name forwarded to the inner <button>. Useful for icon-only usage, and when provided it overrides the accessible name derived from any slotted label text.
127
+ * @default null
128
+ */
129
+ "ariaLabel"?: string | null;
60
130
  /**
61
131
  * Disables the button
62
132
  * @default false
@@ -91,8 +161,54 @@ declare namespace LocalJSX {
91
161
  */
92
162
  "variant"?: 'primary' | 'secondary' | 'tertiary' | 'brand' | 'destructive';
93
163
  }
164
+ interface IpTooltip {
165
+ /**
166
+ * Renders a directional arrow pointing toward the trigger element.
167
+ * @default true
168
+ */
169
+ "arrow"?: boolean;
170
+ /**
171
+ * Delay in milliseconds before the tooltip appears on hover.
172
+ * @default 300
173
+ */
174
+ "delay"?: number;
175
+ /**
176
+ * Prevents the tooltip from showing on hover or focus.
177
+ * @default false
178
+ */
179
+ "disabled"?: boolean;
180
+ /**
181
+ * Maximum width of the tooltip bubble. Use absolute or viewport units — percentage values are not supported as they resolve relative to the trigger element. E.g. "300px", "20rem", "50vw".
182
+ * @default '300px'
183
+ */
184
+ "maxWidth"?: string;
185
+ /**
186
+ * Emitted when the tooltip transitions from visible to hidden.
187
+ */
188
+ "onHide"?: (event: IpTooltipCustomEvent<void>) => void;
189
+ /**
190
+ * Emitted when the tooltip transitions from hidden to visible.
191
+ */
192
+ "onShow"?: (event: IpTooltipCustomEvent<void>) => void;
193
+ /**
194
+ * Placement of the tooltip bubble relative to the trigger element.
195
+ * @default 'top'
196
+ */
197
+ "position"?: 'top' | 'right' | 'bottom' | 'left';
198
+ /**
199
+ * Visual size of the tooltip bubble.
200
+ * @default 'medium'
201
+ */
202
+ "size"?: 'small' | 'medium' | 'large';
203
+ /**
204
+ * Forces the tooltip visible regardless of hover or focus state.
205
+ * @default false
206
+ */
207
+ "visible"?: boolean;
208
+ }
94
209
 
95
210
  interface IpButtonAttributes {
211
+ "ariaLabel": string | null;
96
212
  "variant": 'primary' | 'secondary' | 'tertiary' | 'brand' | 'destructive';
97
213
  "loading": boolean;
98
214
  "disabled": boolean;
@@ -100,9 +216,19 @@ declare namespace LocalJSX {
100
216
  "size": 'small' | 'medium' | 'large';
101
217
  "alignIcon": 'start' | 'end';
102
218
  }
219
+ interface IpTooltipAttributes {
220
+ "position": 'top' | 'right' | 'bottom' | 'left';
221
+ "size": 'small' | 'medium' | 'large';
222
+ "delay": number;
223
+ "visible": boolean;
224
+ "disabled": boolean;
225
+ "arrow": boolean;
226
+ "maxWidth": string;
227
+ }
103
228
 
104
229
  interface IntrinsicElements {
105
230
  "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] };
231
+ "ip-tooltip": Omit<IpTooltip, keyof IpTooltipAttributes> & { [K in keyof IpTooltip & keyof IpTooltipAttributes]?: IpTooltip[K] } & { [K in keyof IpTooltip & keyof IpTooltipAttributes as `attr:${K}`]?: IpTooltipAttributes[K] } & { [K in keyof IpTooltip & keyof IpTooltipAttributes as `prop:${K}`]?: IpTooltip[K] };
106
232
  }
107
233
  }
108
234
  export { LocalJSX as JSX };
@@ -110,6 +236,7 @@ declare module "@stencil/core" {
110
236
  export namespace JSX {
111
237
  interface IntrinsicElements {
112
238
  "ip-button": LocalJSX.IntrinsicElements["ip-button"] & JSXBase.HTMLAttributes<HTMLIpButtonElement>;
239
+ "ip-tooltip": LocalJSX.IntrinsicElements["ip-tooltip"] & JSXBase.HTMLAttributes<HTMLIpTooltipElement>;
113
240
  }
114
241
  }
115
242
  }
@@ -1 +1,2 @@
1
1
  export { IpButton } from './components/ip-button/ip-button';
2
+ export { IpTooltip } from './components/ip-tooltip/ip-tooltip';
@@ -1 +1 @@
1
- function t(t,o,e){const n="undefined"!=typeof HTMLElement?HTMLElement.prototype:null;for(;t&&t!==n;){const n=Object.getOwnPropertyDescriptor(t,o);if(n&&(!e||n.get))return n;t=Object.getPrototypeOf(t)}}var o,e=(o,e)=>{var n;Object.entries(null!=(n=e.o.t)?n:{}).map((([n,[i]])=>{if(31&i||32&i){const i=o[n],r=t(Object.getPrototypeOf(o),n,!0)||Object.getOwnPropertyDescriptor(o,n);r&&Object.defineProperty(o,n,{get(){return r.get.call(this)},set(t){r.set.call(this,t)},configurable:!0,enumerable:!0}),e.i.has(n)?o[n]=e.i.get(n):void 0!==i&&(o[n]=i)}}))},n=t=>{if(t.__stencil__getHostRef)return t.__stencil__getHostRef()},i=(t,o)=>o in t,r=(t,o)=>(0,console.error)(t,o),l=new Map,a=["formAssociatedCallback","formResetCallback","formDisabledCallback","formStateRestoreCallback"],s="undefined"!=typeof window?window:{},c=s.HTMLElement||class{},u={l:0,u:"",jmp:t=>t(),raf:t=>requestAnimationFrame(t),ael:(t,o,e,n)=>t.addEventListener(o,e,n),rel:(t,o,e,n)=>t.removeEventListener(o,e,n),ce:(t,o)=>new CustomEvent(t,o)},d=(()=>{try{return!!s.document.adoptedStyleSheets&&(new CSSStyleSheet,"function"==typeof(new CSSStyleSheet).replaceSync)}catch(t){}return!1})(),p=!!d&&(()=>!!s.document&&Object.getOwnPropertyDescriptor(s.document.adoptedStyleSheets,"length").writable)(),_=!1,b=[],f=[],h=(t,o)=>e=>{t.push(e),_||(_=!0,o&&4&u.l?y(m):u.raf(m))},v=t=>{for(let o=0;o<t.length;o++)try{t[o](performance.now())}catch(t){r(t)}t.length=0},m=()=>{v(b),v(f),(_=b.length>0)&&u.raf(m)},y=t=>Promise.resolve(void 0).then(t),g=h(f,!0),k=t=>{const o=new URL(t,u.u);return o.origin!==s.location.origin?o.href:o.pathname},$=t=>u.u=t;function w(){const t=this.attachShadow({mode:"open"});void 0===o&&(o=null),o&&(p?t.adoptedStyleSheets.push(o):t.adoptedStyleSheets=[...t.adoptedStyleSheets,o])}var x,j=new WeakMap,O=t=>"sc-"+t.p,S=t=>"object"==(t=typeof t)||"function"===t,z=(t,o,...e)=>{let n=null,i=null,r=!1,l=!1;const a=[],s=o=>{for(let e=0;e<o.length;e++)n=o[e],Array.isArray(n)?s(n):null!=n&&"boolean"!=typeof n&&((r="function"!=typeof t&&!S(n))&&(n+=""),r&&l?a[a.length-1]._+=n:a.push(r?E(null,n):n),l=r)};if(s(e),o){o.key&&(i=o.key);{const t=o.className||o.class;t&&(o.class="object"!=typeof t?t:Object.keys(t).filter((o=>t[o])).join(" "))}}if("function"==typeof t)return t(null===o?{}:o,a,M);const c=E(t,null);return c.h=o,a.length>0&&(c.v=a),c.m=i,c},E=(t,o)=>({l:0,k:t,_:null!=o?o:null,$:null,v:null,h:null,m:null}),C={},M={forEach:(t,o)=>t.map(A).forEach(o),map:(t,o)=>t.map(A).map(o).map(L)},A=t=>({vattrs:t.h,vchildren:t.v,vkey:t.m,vname:t.j,vtag:t.k,vtext:t._}),L=t=>{if("function"==typeof t.vtag){const o={...t.vattrs};return t.vkey&&(o.key=t.vkey),t.vname&&(o.name=t.vname),z(t.vtag,o,...t.vchildren||[])}const o=E(t.vtag,t.vtext);return o.h=t.vattrs,o.v=t.vchildren,o.m=t.vkey,o.j=t.vname,o},R=(t,o,e)=>null==t||S(t)?t:4&o?(e&&"string"==typeof t||"false"!==t)&&(""===t||!!t):1&o?t+"":t,D=(t,o,e,r,l,a)=>{if(e===r)return;let c=i(t,o),d=o.toLowerCase();if("class"===o){const o=t.classList,n=P(e);let i=P(r);o.remove(...n.filter((t=>t&&!i.includes(t)))),o.add(...i.filter((t=>t&&!n.includes(t))))}else if("key"===o);else if(t.__lookupSetter__(o)||"o"!==o[0]||"n"!==o[1]){if("a"===o[0]&&o.startsWith("attr:")){const e=o.slice(5);let i;{const o=n(t);if(o&&o.o&&o.o.t){const t=o.o.t[e];t&&t[1]&&(i=t[1])}}return i||(i=e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()),void(null==r||!1===r?!1===r&&""!==t.getAttribute(i)||t.removeAttribute(i):t.setAttribute(i,!0===r?"":r))}if("p"===o[0]&&o.startsWith("prop:")){const e=o.slice(5);try{t[e]=r}catch(t){}return}{const n=S(r);if((c||n&&null!==r)&&!l)try{if(t.tagName.includes("-"))t[o]!==r&&(t[o]=r);else{const n=null==r?"":r;"list"===o?c=!1:null!=e&&t[o]===n||("function"==typeof t.__lookupSetter__(o)?t[o]=n:t.setAttribute(o,n))}}catch(t){}null==r||!1===r?!1===r&&""!==t.getAttribute(o)||t.removeAttribute(o):(!c||4&a||l)&&!n&&1===t.nodeType&&t.setAttribute(o,r=!0===r?"":r)}}else if(o="-"===o[2]?o.slice(3):i(s,d)?d.slice(2):d[2]+o.slice(3),e||r){const n=o.endsWith(U);o=o.replace(N,""),e&&u.rel(t,o,e,n),r&&u.ael(t,o,r,n)}},H=/\s/,P=t=>("object"==typeof t&&t&&"baseVal"in t&&(t=t.baseVal),t&&"string"==typeof t?t.split(H):[]),U="Capture",N=RegExp(U+"$"),W=(t,o,e)=>{const n=11===o.$.nodeType&&o.$.host?o.$.host:o.$,i=t&&t.h||{},r=o.h||{};for(const t of V(Object.keys(i)))t in r||D(n,t,i[t],void 0,e,o.l);for(const t of V(Object.keys(r)))D(n,t,i[t],r[t],e,o.l)};function V(t){return t.includes("ref")?[...t.filter((t=>"ref"!==t)),"ref"]:t}var q=!1,F=!1,T=(t,o,e)=>{const n=o.v[e];let i,r,l=0;if(null!=n._)i=n.$=s.document.createTextNode(n._);else{if(!s.document)throw Error("You are trying to render a Stencil component in an environment that doesn't support the DOM.");if(i=n.$=s.document.createElement(n.k),W(null,n,F),n.v){const o="template"===n.k?i.content:i;for(l=0;l<n.v.length;++l)r=T(t,n,l),r&&o.appendChild(r)}}return i["s-hn"]=x,i},I=(t,o,e,n,i,r)=>{let l,a=t;for(a.shadowRoot&&a.tagName===x&&(a=a.shadowRoot),"template"===e.k&&(a=a.content);i<=r;++i)n[i]&&(l=T(null,e,i),l&&(n[i].$=l,G(a,l,o)))},Y=(t,o,e)=>{for(let n=o;n<=e;++n){const o=t[n];if(o){const t=o.$;t&&t.remove()}}},Z=(t,o,e=!1)=>t.k===o.k&&(e?(e&&!t.m&&o.m&&(t.m=o.m),!0):t.m===o.m),B=(t,o,e=!1)=>{const n=o.$=t.$,i=t.v,r=o.v,l=o._;null==l?("slot"!==o.k||q||t.j!==o.j&&(o.$["s-sn"]=o.j||"",(t=>{u.l|=1;const o=t.closest(x.toLowerCase());if(null!=o){const e=Array.from(o.__childNodes||o.childNodes).find((t=>t["s-cr"])),n=Array.from(t.__childNodes||t.childNodes);for(const t of e?n.reverse():n)null!=t["s-sh"]&&(G(o,t,null!=e?e:null),t["s-sh"]=void 0)}u.l&=-2})(o.$.parentElement)),W(t,o,F),null!==i&&null!==r?((t,o,e,n,i=!1)=>{let r,l,a=0,s=0,c=0,u=0,d=o.length-1,p=o[0],_=o[d],b=n.length-1,f=n[0],h=n[b];const v="template"===e.k?t.content:t;for(;a<=d&&s<=b;)if(null==p)p=o[++a];else if(null==_)_=o[--d];else if(null==f)f=n[++s];else if(null==h)h=n[--b];else if(Z(p,f,i))B(p,f,i),p=o[++a],f=n[++s];else if(Z(_,h,i))B(_,h,i),_=o[--d],h=n[--b];else if(Z(p,h,i))B(p,h,i),G(v,p.$,_.$.nextSibling),p=o[++a],h=n[--b];else if(Z(_,f,i))B(_,f,i),G(v,_.$,p.$),_=o[--d],f=n[++s];else{for(c=-1,u=a;u<=d;++u)if(o[u]&&null!==o[u].m&&o[u].m===f.m){c=u;break}c>=0?(l=o[c],l.k!==f.k?r=T(o&&o[s],e,c):(B(l,f,i),o[c]=void 0,r=l.$),f=n[++s]):(r=T(o&&o[s],e,s),f=n[++s]),r&&G(p.$.parentNode,r,p.$)}a>d?I(t,null==n[b+1]?null:n[b+1].$,e,n,s,b):s>b&&Y(o,a,d)})(n,i,o,r,e):null!==r?(null!==t._&&(n.textContent=""),I(n,null,o,r,0,r.length-1)):!e&&null!==i&&Y(i,0,i.length-1)):t._!==l&&(n.data=l)},G=(t,o,e)=>t.__insertBefore?t.__insertBefore(o,e):null==t?void 0:t.insertBefore(o,e),J=(t,o,e=!1)=>{const n=t.$hostElement$,i=t.o,r=t.O||E(null,null),l=(t=>t&&t.k===C)(o)?o:z(null,null,o);if(x=n.tagName,i.S&&(l.h=l.h||{},i.S.forEach((([t,o])=>{l.h[o]=n[t]}))),e&&l.h)for(const t of Object.keys(l.h))n.hasAttribute(t)&&!["key","ref","style","class"].includes(t)&&(l.h[t]=n[t]);l.k=null,l.l|=4,t.O=l,l.$=r.$=n.shadowRoot||n,q=!(!(1&i.l)||128&i.l),B(r,l,e)},K=(t,o)=>{if(o&&!t.C&&o["s-p"]){const e=o["s-p"].push(new Promise((n=>t.C=()=>{o["s-p"].splice(e-1,1),n()})))}},Q=(t,o)=>{if(t.l|=16,4&t.l)return void(t.l|=512);K(t,t.M);const e=()=>X(t,o);if(!o)return g(e);queueMicrotask((()=>{e()}))},X=(t,o)=>{const e=t.$hostElement$,n=e;if(!n)throw Error(`Can't render component <${e.tagName.toLowerCase()} /> with invalid Stencil runtime! Make sure this imported component is compiled with a \`externalRuntime: true\` flag. For more information, please refer to https://stenciljs.com/docs/custom-elements#externalruntime`);let i;return i=lt(n,o?"componentWillLoad":"componentWillUpdate",void 0,e),i=tt(i,(()=>lt(n,"componentWillRender",void 0,e))),tt(i,(()=>et(t,n,o)))},tt=(t,o)=>ot(t)?t.then(o).catch((t=>{console.error(t),o()})):o(),ot=t=>t instanceof Promise||t&&t.then&&"function"==typeof t.then,et=async(t,o,e)=>{var n;const i=t.$hostElement$,r=i["s-rc"];e&&(t=>{const o=t.o,e=t.$hostElement$,n=o.l,i=((t,o)=>{var e,n,i;const r=O(o),a=l.get(r);if(!s.document)return r;if(t=11===t.nodeType?t:s.document,a)if("string"==typeof a){let i,l=j.get(t=t.head||t);if(l||j.set(t,l=new Set),!l.has(r)){i=s.document.createElement("style"),i.textContent=a;const c=null!=(e=u.A)?e:function(){var t,o,e;return null!=(e=null==(o=null==(t=s.document.head)?void 0:t.querySelector('meta[name="csp-nonce"]'))?void 0:o.getAttribute("content"))?e:void 0}();if(null!=c&&i.setAttribute("nonce",c),!(1&o.l))if("HEAD"===t.nodeName){const o=t.querySelectorAll("link[rel=preconnect]"),e=o.length>0?o[o.length-1].nextSibling:t.querySelector("style");t.insertBefore(i,(null==e?void 0:e.parentNode)===t?e:null)}else if("host"in t)if(d){const o=new(null!=(n=t.defaultView)?n:t.ownerDocument.defaultView).CSSStyleSheet;o.replaceSync(a),p?t.adoptedStyleSheets.unshift(o):t.adoptedStyleSheets=[o,...t.adoptedStyleSheets]}else{const o=t.querySelector("style");o?o.textContent=a+o.textContent:t.prepend(i)}else t.append(i);1&o.l&&t.insertBefore(i,null),4&o.l&&(i.textContent+="slot-fb{display:contents}slot-fb[hidden]{display:none}"),l&&l.add(r)}}else{let o=j.get(t);if(o||j.set(t,o=new Set),!o.has(r)){const e=null!=(i=t.defaultView)?i:t.ownerDocument.defaultView;let n;if(a.constructor===e.CSSStyleSheet)n=a;else{n=new e.CSSStyleSheet;for(let t=0;t<a.cssRules.length;t++)n.insertRule(a.cssRules[t].cssText,t)}p?t.adoptedStyleSheets.push(n):t.adoptedStyleSheets=[...t.adoptedStyleSheets,n],o.add(r)}}return r})(e.shadowRoot?e.shadowRoot:e.getRootNode(),o);10&n&&(e["s-sc"]=i,e.classList.add(i+"-h"))})(t);nt(t,o,i,e),r&&(r.map((t=>t())),i["s-rc"]=void 0);{const o=null!=(n=i["s-p"])?n:[],e=()=>it(t);0===o.length?e():(Promise.all(o).then(e).catch(e),t.l|=4,o.length=0)}},nt=(t,o,e,n)=>{try{o=o.render(),t.l&=-17,t.l|=2,J(t,o,n)}catch(o){r(o,t.$hostElement$)}return null},it=t=>{const o=t.$hostElement$,e=o,n=t.M;lt(e,"componentDidRender",void 0,o),64&t.l?lt(e,"componentDidUpdate",void 0,o):(t.l|=64,at(o),lt(e,"componentDidLoad",void 0,o),t.L(o),n||rt()),t.C&&(t.C(),t.C=void 0),512&t.l&&y((()=>Q(t,!1))),t.l&=-517},rt=()=>{y((()=>(t=>{const o=u.ce("appload",{detail:{namespace:"pixel"}});return t.dispatchEvent(o),o})(s)))},lt=(t,o,e,n)=>{if(t&&t[o])try{return t[o](e)}catch(t){r(t,n)}},at=t=>t.classList.add("hydrated"),st=(t,o,e,i)=>{const r=n(t);if(!r)return;const l=t,a=r.i.get(o),s=r.l,c=l;if((e=R(e,i.t[o][0],!!(64&i.l)))!==a&&(!Number.isNaN(a)||!Number.isNaN(e))&&(r.i.set(o,e),2&s)){if(c.componentShouldUpdate&&!1===c.componentShouldUpdate(e,a,o)&&!(16&s))return;16&s||Q(r,!1)}},ct=(o,e,i)=>{var r,l;const s=o.prototype;if(64&e.l&&1&i&&a.forEach((t=>{const o=s[t];Object.defineProperty(s,t,{value(...e){var i;const r=n(this),l=this;l?"function"==typeof o&&o.call(l,...e):null==(i=null==r?void 0:r.R)||i.then((o=>{const n=o[t];"function"==typeof n&&n.call(o,...e)}))}})})),e.t){const i=Object.entries(null!=(r=e.t)?r:{});i.map((([o,[i]])=>{if(31&i||32&i){const{get:r,set:l}=t(s,o)||{};r&&(e.t[o][0]|=2048),l&&(e.t[o][0]|=4096),Object.defineProperty(s,o,{get(){return r?r.apply(this):((t,o)=>n(this).i.get(o))(0,o)},configurable:!0,enumerable:!0}),Object.defineProperty(s,o,{set(t){const r=n(this);if(r){if(l)return void 0===(32&i?this[o]:r.$hostElement$[o])&&r.i.get(o)&&(t=r.i.get(o)),l.call(this,R(t,i,!!(64&e.l))),void st(this,o,t=32&i?this[o]:r.$hostElement$[o],e);st(this,o,t,e)}}})}}));{const t=new Map;s.attributeChangedCallback=function(o,r,l){u.jmp((()=>{var a;const c=t.get(o),u=n(this);if(this.hasOwnProperty(c),s.hasOwnProperty(c)&&"number"==typeof this[c]&&this[c]==l)return;if(null==c){const t=null==u?void 0:u.l;if(u&&t&&!(8&t)&&l!==r){const n=this,i=null==(a=e.D)?void 0:a[o];null==i||i.forEach((e=>{const[[i,a]]=Object.entries(e);null!=n[i]&&(128&t||1&a)&&n[i].call(n,l,r,o)}))}return}const d=i.find((([t])=>t===c));d&&4&d[1][0]&&(l=null!==l&&"false"!==l);const p=Object.getOwnPropertyDescriptor(s,c);l==this[c]||p.get&&!p.set||(this[c]=l)}))},o.observedAttributes=Array.from(new Set([...Object.keys(null!=(l=e.D)?l:{}),...i.filter((([t,o])=>31&o[0])).map((([o,n])=>{var i;const r=n[1]||o;return t.set(r,o),512&n[0]&&(null==(i=e.S)||i.push([o,r])),r}))]))}}return o},ut=(t,o)=>o,dt=t=>u.A=t,pt=t=>Object.assign(u,t);function _t(t,o){J({o:{l:0,p:o.tagName},$hostElement$:o},t)}const bt=((t,o)=>{const i={l:321,p:o[1]};try{i.t=o[2],i.S=[];const a=t.prototype.connectedCallback,s=t.prototype.disconnectedCallback;return Object.assign(t.prototype,{__hasHostListenerAttached:!1,__registerHost(){((t,o)=>{const n={l:0,$hostElement$:t,o,i:new Map,H:new Map};n.R=new Promise((t=>n.L=t)),t["s-p"]=[],t["s-rc"]=[];const i=n;t.__stencil__getHostRef=()=>i,512&o.l&&e(t,n)})(this,i)},connectedCallback(){if(!this.__hasHostListenerAttached){if(!n(this))return;this.__hasHostListenerAttached=!0}(t=>{if(!(1&u.l)){const o=n(t);if(!o)return;const e=o.o,i=()=>{};if(1&o.l)(null==o?void 0:o.P)||(null==o?void 0:o.R)&&o.R.then((()=>{}));else{o.l|=1;{let e=t;for(;e=e.parentNode||e.host;)if(e["s-p"]){K(o,o.M=e);break}}e.t&&Object.entries(e.t).map((([o,[e]])=>{if(31&e&&Object.prototype.hasOwnProperty.call(t,o)){const e=t[o];delete t[o],t[o]=e}})),(async(t,o,e)=>{let n;try{if(!(32&o.l)&&(o.l|=32,n=t.constructor,customElements.whenDefined(t.localName).then((()=>o.l|=128)),n&&n.style)){let t;"string"==typeof n.style&&(t=n.style);const o=O(e);if(!l.has(o)){const n=()=>{};((t,o,e)=>{let n=l.get(t);d&&e?(n=n||new CSSStyleSheet,"string"==typeof n?n=o:n.replaceSync(o)):n=o,l.set(t,n)})(o,t,!!(1&e.l)),n()}}const i=o.M,r=()=>Q(o,!0);i&&i["s-rc"]?i["s-rc"].push(r):r()}catch(e){r(e,t),o.C&&(o.C(),o.C=void 0),o.L&&o.L(t)}})(t,o,e)}i()}})(this),a&&a.call(this)},disconnectedCallback(){(async t=>{j.has(t)&&j.delete(t),t.shadowRoot&&j.has(t.shadowRoot)&&j.delete(t.shadowRoot)})(this),s&&s.call(this)},__attachShadow(){if(this.shadowRoot){if("open"!==this.shadowRoot.mode)throw Error(`Unable to re-use existing shadow root for ${i.p}! Mode is set to ${this.shadowRoot.mode} but Stencil only supports open shadow roots.`)}else w.call(this,i)}}),Object.defineProperty(t,"is",{value:i.p,configurable:!0}),ct(t,i,3)}catch(o){return r(o),t}})(class extends c{constructor(t){super(),!1!==t&&this.__registerHost(),this.__attachShadow(),this.internals=this.attachInternals(),this.variant="primary",this.loading=!1,this.disabled=!1,this.type="submit",this.size="medium",this.alignIcon="start",this.handleClick=()=>"submit"===this.type?this.internals.form?.requestSubmit():"reset"===this.type?this.internals.form?.reset():void 0}render(){const t=this.disabled||this.loading;return z("button",{key:"661cfd51077aeed83e44c9618e44975cdfd059eb",class:`ip-button ip-button--${this.variant} ip-button--${this.size}`,type:"button",disabled:t,"aria-disabled":t?"true":"false","aria-busy":this.loading?"true":"false",onClick:this.handleClick},"start"===this.alignIcon&&z("slot",{key:"icon-start",name:"icon"}),z("span",{key:"54fd1362c6c897601b98c37cf430a0c48c715441",class:"ip-button__label ip-button__label--"+this.size},z("slot",{key:"54847647ff736d1515b64243765728c92e69aafe"})),"end"===this.alignIcon&&z("slot",{key:"icon-end",name:"icon"}),this.loading&&z(ut,{key:"7862ed898343b665288c6abd9309c3403597c8c9"},z("span",{key:"38629b0ac7734f83ca9f0e984599af9c388b5788",class:"ip-button__spinner","aria-hidden":"true"}),z("span",{key:"16b0b262e88a08144404357841809762f82a870e",class:"ip-button__sr-only"},"Loading...")))}static get formAssociated(){return!0}static get style(){return".ip-button{border:none;border-radius:var(--ip_radius_size_medium);margin:0;cursor:pointer;position:relative;overflow:hidden;display:inline-flex;align-items:center;justify-content:center;font-family:var(--ip_typography_font_family_primary);transition:background-color 150ms ease-in-out, color 150ms ease-in-out}.ip-button:disabled{cursor:not-allowed}.ip-button:focus-visible{outline:2px solid var(--ip_color_button_focus_default);outline-offset:2px}.ip-button--small{padding:var(--ip_spacing_space_100) var(--ip_spacing_space_150);gap:var(--ip_spacing_space_125);font-size:var(--ip_typography_body_font_size_small)}.ip-button--medium{padding:var(--ip_spacing_space_125) var(--ip_spacing_space_200);gap:var(--ip_spacing_space_150);font-size:var(--ip_typography_body_font_size_medium)}.ip-button--large{padding:var(--ip_spacing_space_150) var(--ip_spacing_space_250);gap:var(--ip_spacing_space_200);font-size:var(--ip_typography_body_font_size_large)}.ip-button--primary{background-color:var(--ip_color_button_background_primary_default);color:var(--ip_color_button_text_primary_default)}.ip-button--primary:hover:not(:disabled){background-color:var(--ip_color_button_background_primary_hover)}.ip-button--primary:active:not(:disabled){background-color:var(--ip_color_button_background_primary_active)}.ip-button--primary:disabled{background-color:var(--ip_color_button_background_primary_disabled);color:var(--ip_color_button_text_primary_disabled)}.ip-button--secondary{background-color:var(--ip_color_button_background_secondary_default);color:var(--ip_color_button_text_secondary_default)}.ip-button--secondary:hover:not(:disabled){background-color:var(--ip_color_button_background_secondary_hover)}.ip-button--secondary:active:not(:disabled){background-color:var(--ip_color_button_background_secondary_active)}.ip-button--secondary:disabled{background-color:var(--ip_color_button_background_secondary_disabled);color:var(--ip_color_button_text_secondary_disabled)}.ip-button--tertiary{background-color:var(--ip_color_button_background_tertiary_default);color:var(--ip_color_button_text_tertiary_default)}.ip-button--tertiary:hover:not(:disabled){background-color:var(--ip_color_button_background_tertiary_hover)}.ip-button--tertiary:active:not(:disabled){background-color:var(--ip_color_button_background_tertiary_active)}.ip-button--tertiary:disabled{background-color:var(--ip_color_button_background_tertiary_disabled);color:var(--ip_color_button_text_tertiary_disabled)}.ip-button--brand{background-color:var(--ip_color_button_background_brand_default);color:var(--ip_color_button_text_brand_default)}.ip-button--brand:hover:not(:disabled){background-color:var(--ip_color_button_background_brand_hover)}.ip-button--brand:active:not(:disabled){background-color:var(--ip_color_button_background_brand_active)}.ip-button--brand:disabled{background-color:var(--ip_color_button_background_brand_disabled);color:var(--ip_color_button_text_brand_disabled)}.ip-button--destructive{background-color:var(--ip_color_button_background_destructive_default);color:var(--ip_color_button_text_destructive_default)}.ip-button--destructive:hover:not(:disabled){background-color:var(--ip_color_button_background_destructive_hover)}.ip-button--destructive:active:not(:disabled){background-color:var(--ip_color_button_background_destructive_active)}.ip-button--destructive:disabled{background-color:var(--ip_color_button_background_destructive_disabled);color:var(--ip_color_button_text_destructive_disabled)}.ip-button__label{display:inline-flex;align-items:center}.ip-button__label--small{height:18px}.ip-button__label--medium{height:20px}.ip-button__label--large{height:22px}.ip-button__spinner{width:0.75em;height:0.75em;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:ip-button-spin 900ms linear infinite;flex-shrink:0}.ip-button__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}@keyframes ip-button-spin{to{transform:rotate(360deg)}}::slotted([slot=icon]){display:inline-flex !important;align-items:center;justify-content:center}:host([size=small]) ::slotted([slot=icon]){font-size:var(--ip_iconography_size_small);width:18px !important;height:18px !important}:host([size=medium]) ::slotted([slot=icon]){font-size:var(--ip_iconography_size_medium);width:20px !important;height:20px !important}:host([size=large]) ::slotted([slot=icon]){font-size:var(--ip_iconography_size_large);width:22px !important;height:22px !important}"}},[321,"ip-button",{variant:[513],loading:[516],disabled:[516],type:[513],size:[513],alignIcon:[513,"align-icon"]}]);function ft(){"undefined"!=typeof customElements&&["ip-button"].forEach((t=>{"ip-button"===t&&(customElements.get(t)||customElements.define(t,bt))}))}ft();export{bt as IpButton,ft as d,k as getAssetPath,_t as render,$ as setAssetPath,dt as setNonce,pt as setPlatformOptions}
1
+ export{g as getAssetPath,r as render,s as setAssetPath,a as setNonce,b as setPlatformOptions}from"./p-BWyvzXuA.js";export{I as IpButton}from"./p-CW9GjbMh.js";export{I as IpTooltip}from"./p-CHBDz3Co.js";
@@ -8,14 +8,15 @@ Clickable button component with support for visual variants, loading state, and
8
8
 
9
9
  ## Attributes
10
10
 
11
- | Attribute | Type | Default | Values |
12
- | ----------- | ------- | ----------- | -------------------------------------------------------------------- |
13
- | `variant` | string | `"primary"` | `"primary"`, `"secondary"`, `"tertiary"`, `"brand"`, `"destructive"` |
14
- | `size` | string | `"medium"` | `"small"`, `"medium"`, `"large"` |
15
- | `loading` | boolean | `false` | `true`, `false` |
16
- | `disabled` | boolean | `false` | `true`, `false` |
17
- | `type` | string | `"submit"` | `"submit"`, `"reset"`, `"button"` |
18
- | `alignIcon` | string | `"start"` | `"start"`, `"end"` |
11
+ | Attribute | Type | Default | Values |
12
+ | ------------ | ------- | ----------- | -------------------------------------------------------------------- |
13
+ | `variant` | string | `"primary"` | `"primary"`, `"secondary"`, `"tertiary"`, `"brand"`, `"destructive"` |
14
+ | `size` | string | `"medium"` | `"small"`, `"medium"`, `"large"` |
15
+ | `loading` | boolean | `false` | `true`, `false` |
16
+ | `disabled` | boolean | `false` | `true`, `false` |
17
+ | `type` | string | `"submit"` | `"submit"`, `"reset"`, `"button"` |
18
+ | `alignIcon` | string | `"start"` | `"start"`, `"end"` |
19
+ | `aria-label` | string | — | Any string |
19
20
 
20
21
  **size** — Controls the size of the button. Defaults to `"medium"`. Affects padding, gap, and font size.
21
22
 
@@ -57,6 +58,8 @@ Clickable button component with support for visual variants, loading state, and
57
58
  | _(default)_ | Button label text |
58
59
  | `icon` | Optional icon. Position is controlled by the `alignIcon` prop (`"start"` or `"end"`) |
59
60
 
61
+ > **Icon-only buttons:** When no label text is slotted, the button has no visible accessible name. In this case, set `aria-label` on the `<ip-button>` host element — it is automatically forwarded to the inner `<button>`. Example: `<ip-button aria-label="Delete item"><i slot="icon">…</i></ip-button>`.
62
+
60
63
  ## Other Tokens
61
64
 
62
65
  | SCSS variable | CSS variable | Description |
@@ -151,10 +154,14 @@ import { IpButton } from '@norconsult-digital-public/isypixel/web-components/rea
151
154
 
152
155
  ### Vue
153
156
 
154
- ```tsx
157
+ ```vue
158
+ <script setup lang="ts">
155
159
  import { IpButton } from '@norconsult-digital-public/isypixel/web-components/vue';
160
+ </script>
156
161
 
157
- <IpButton variant='primary'>Click me</IpButton>;
162
+ <template>
163
+ <IpButton variant="primary">Click me</IpButton>
164
+ </template>
158
165
  ```
159
166
 
160
167
  ### Angular
@@ -1 +1 @@
1
- import{IpButton as o,d as t}from"./index.js";const s=o,n=t;export{s as IpButton,n as defineCustomElement}
1
+ import{I as o,d as s}from"./p-CW9GjbMh.js";const p=o,r=s;export{p as IpButton,r as defineCustomElement}
@@ -0,0 +1,151 @@
1
+ # ip-tooltip
2
+
3
+ Tooltip component that wraps a trigger element and displays non-interactive content above, below, to the right, or to the left of the trigger on hover and focus.
4
+
5
+ **Storybook:** https://pixel.isy.no/storybook/?path=/docs/core-ui-ip-tooltip-usage--docs
6
+
7
+ > 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.
8
+
9
+ ## Attributes
10
+
11
+ | Attribute | Type | Default | Values | Description |
12
+ | ---------- | ------- | ---------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
13
+ | `position` | string | `"top"` | `"top"`, `"right"`, `"bottom"`, `"left"` | Placement of the tooltip bubble relative to the trigger element |
14
+ | `size` | string | `"medium"` | `"small"`, `"medium"`, `"large"` | Visual size of the tooltip bubble (affects padding and font size) |
15
+ | `delay` | number | `300` | Any non-negative integer | Delay in milliseconds before the tooltip appears on hover |
16
+ | `visible` | boolean | `false` | `true`, `false` | Forces the tooltip visible regardless of hover or focus state |
17
+ | `disabled` | boolean | `false` | `true`, `false` | Prevents the tooltip from showing on hover or focus |
18
+ | `arrow` | boolean | `true` | `true`, `false` | Renders a directional arrow pointing toward the trigger element |
19
+ | `maxWidth` | string | `"300px"` | Absolute or viewport units (`px`, `rem`, `vw`) — **not** `%` | Maximum width of the tooltip bubble. Percentage values are not supported — they resolve relative to the trigger element, not the viewport. |
20
+
21
+ **position** — Controls where the tooltip bubble appears relative to the trigger.
22
+
23
+ - `"top"` (default) — tooltip appears above the trigger
24
+ - `"right"` — tooltip appears to the right of the trigger
25
+ - `"bottom"` — tooltip appears below the trigger
26
+ - `"left"` — tooltip appears to the left of the trigger
27
+
28
+ **delay** — Applied only on hover (mouseenter). Tooltip appears immediately on focus for keyboard accessibility.
29
+
30
+ **visible** — Use for programmatic control, e.g. always-on help tooltips. When `true`, the tooltip is shown regardless of whether the user is hovering or has focused the trigger. `show` and `hide` events are still emitted when this prop changes.
31
+
32
+ > **Note:** Pressing Escape does **not** dismiss a `visible=true` tooltip. Escape only clears the internal hover/focus state — it does not modify the `visible` prop. To dismiss programmatically, set `visible` to `false` from the outside.
33
+
34
+ **disabled** — When `true`, hover and focus interactions are ignored. Setting `visible` while `disabled` is `true` still shows the tooltip.
35
+
36
+ ## Slots
37
+
38
+ | Slot | Description |
39
+ | ----------- | ---------------------------------------------------------------------------------------------------------------- |
40
+ | `trigger` | The element that triggers the tooltip on hover and focus. Must be interactive (e.g. `<button>`) |
41
+ | _(default)_ | The tooltip content — plain text or static HTML. Must not contain interactive elements (links, buttons, inputs). |
42
+
43
+ > **Limitation:** Interactive content (links, buttons, inputs) inside the default slot is not supported. The tooltip bubble is not keyboard-navigable. Content requiring user interaction must use a popover or dialog instead.
44
+
45
+ > **Known limitation — `aria-describedby` and Shadow DOM:** The `aria-describedby` attribute linking the trigger to the tooltip is set on an internal wrapper div, not on the slotted trigger element. Due to Shadow DOM cross-root ARIA isolation, the tooltip ID (which lives inside the shadow root) cannot be referenced from a light DOM element. As a result, some screen readers may not announce the tooltip content as a description of the trigger. The tooltip's `role="tooltip"` is still present and will be announced on focus in supporting browsers.
46
+
47
+ ## Events
48
+
49
+ | Event | Payload | When |
50
+ | ------ | ------- | ---------------------------------------------------------------- |
51
+ | `show` | `void` | Emitted once when the tooltip transitions from hidden to visible |
52
+ | `hide` | `void` | Emitted once when the tooltip transitions from visible to hidden |
53
+
54
+ ## Design tokens
55
+
56
+ | SCSS variable | CSS variable | Role |
57
+ | ----------------------------------------- | ------------------------------------------ | ----------------------------------------------------------- |
58
+ | `$ip_color_surface_primary_inverse` | `--ip_color_surface_primary_inverse` | Tooltip background (dark in light mode, light in dark mode) |
59
+ | `$ip_color_text_primary_black_inverse` | `--ip_color_text_primary_black_inverse` | Tooltip text color |
60
+ | `$ip_radius_size_medium` | `--ip_radius_size_medium` | Tooltip bubble border-radius |
61
+ | `$ip_typography_font_family_primary` | `--ip_typography_font_family_primary` | Tooltip font family |
62
+ | `$ip_typography_body_line_height_default` | `--ip_typography_body_line_height_default` | Tooltip line height |
63
+ | `$ip_typography_body_font_size_small` | `--ip_typography_body_font_size_small` | Font size for `size="small"` |
64
+ | `$ip_typography_body_font_size_medium` | `--ip_typography_body_font_size_medium` | Font size for `size="medium"` |
65
+ | `$ip_typography_body_font_size_large` | `--ip_typography_body_font_size_large` | Font size for `size="large"` |
66
+
67
+ ## Usage
68
+
69
+ ### HTML
70
+
71
+ > Attribute names must be **kebab-case** in HTML: use `max-width`, not `maxWidth`.
72
+
73
+ ```js
74
+ import '@norconsult-digital-public/isypixel/web-components/ip-tooltip.js';
75
+ ```
76
+
77
+ ```html
78
+ <ip-tooltip position="top">
79
+ <button slot="trigger">Hover me</button>
80
+ Helpful information about this action.
81
+ </ip-tooltip>
82
+ ```
83
+
84
+ ### React
85
+
86
+ ```tsx
87
+ import { IpTooltip } from '@norconsult-digital-public/isypixel/web-components/react';
88
+
89
+ <IpTooltip position='top'>
90
+ <button slot='trigger'>Hover me</button>
91
+ Helpful information about this action.
92
+ </IpTooltip>;
93
+ ```
94
+
95
+ ### Vue
96
+
97
+ ```vue
98
+ <script setup lang="ts">
99
+ import { IpTooltip } from '@norconsult-digital-public/isypixel/web-components/vue';
100
+ </script>
101
+
102
+ <template>
103
+ <IpTooltip position="top">
104
+ <button slot="trigger">Hover me</button>
105
+ Helpful information about this action.
106
+ </IpTooltip>
107
+ </template>
108
+ ```
109
+
110
+ ### Angular
111
+
112
+ ```ts
113
+ import { IpTooltip } from '@norconsult-digital-public/isypixel/web-components/angular';
114
+ ```
115
+
116
+ ```html
117
+ <ip-tooltip position="top">
118
+ <button slot="trigger">Hover me</button>
119
+ Helpful information about this action.
120
+ </ip-tooltip>
121
+ ```
122
+
123
+ ### Svelte
124
+
125
+ ```svelte
126
+ <script lang="ts">
127
+ import '@norconsult-digital-public/isypixel/web-components/ip-tooltip.js';
128
+ </script>
129
+
130
+ <ip-tooltip position="top">
131
+ <button slot="trigger">Hover me</button>
132
+ Helpful information about this action.
133
+ </ip-tooltip>
134
+ ```
135
+
136
+ ### Blazor
137
+
138
+ > Attribute names must be **kebab-case** in Blazor HTML.
139
+
140
+ Copy `ip-tooltip.js` to `wwwroot/lib/isypixel/components/` at build time. See `llm.md` in the package root for the MSBuild target.
141
+
142
+ ```html
143
+ <script type="module" src="lib/isypixel/components/ip-tooltip.js"></script>
144
+
145
+ <ip-tooltip position="top">
146
+ <button slot="trigger">Hover me</button>
147
+ Helpful information about this action.
148
+ </ip-tooltip>
149
+ ```
150
+
151
+ - Boolean attribute `visible` must be set as `visible="true"` (string value) — Blazor does not reliably render bare boolean attributes on custom elements.
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../../types/components";
2
+
3
+ interface IpTooltip extends Components.IpTooltip, HTMLElement {}
4
+ export const IpTooltip: {
5
+ prototype: IpTooltip;
6
+ new (): IpTooltip;
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 s}from"./p-CHBDz3Co.js";const p=o,r=s;export{p as IpTooltip,r as defineCustomElement}
@@ -0,0 +1 @@
1
+ function t(t,e,n){const l="undefined"!=typeof HTMLElement?HTMLElement.prototype:null;for(;t&&t!==l;){const l=Object.getOwnPropertyDescriptor(t,e);if(l&&(!n||l.get))return l;t=Object.getPrototypeOf(t)}}var e,n=(e,n)=>{var l;Object.entries(null!=(l=n.l.t)?l:{}).map((([l,[o]])=>{if(31&o||32&o){const o=e[l],s=t(Object.getPrototypeOf(e),l,!0)||Object.getOwnPropertyDescriptor(e,l);s&&Object.defineProperty(e,l,{get(){return s.get.call(this)},set(t){s.set.call(this,t)},configurable:!0,enumerable:!0}),n.o.has(l)?e[l]=n.o.get(l):void 0!==o&&(e[l]=o)}}))},l=t=>{if(t.__stencil__getHostRef)return t.__stencil__getHostRef()},o=(t,e)=>e in t,s=(t,e)=>(0,console.error)(t,e),i=new Map,r=["formAssociatedCallback","formResetCallback","formDisabledCallback","formStateRestoreCallback"],c="undefined"!=typeof window?window:{},u=c.HTMLElement||class{},a={i:0,u:"",jmp:t=>t(),raf:t=>requestAnimationFrame(t),ael:(t,e,n,l)=>t.addEventListener(e,n,l),rel:(t,e,n,l)=>t.removeEventListener(e,n,l),ce:(t,e)=>new CustomEvent(t,e)},f=(()=>{var t;let e=!1;try{null==(t=c.document)||t.addEventListener("e",null,Object.defineProperty({},"passive",{get(){e=!0}}))}catch(t){}return e})(),d=(()=>{try{return!!c.document.adoptedStyleSheets&&(new CSSStyleSheet,"function"==typeof(new CSSStyleSheet).replaceSync)}catch(t){}return!1})(),p=!!d&&(()=>!!c.document&&Object.getOwnPropertyDescriptor(c.document.adoptedStyleSheets,"length").writable)(),h=!1,m=[],b=[],y=(t,e)=>n=>{t.push(n),h||(h=!0,e&&4&a.i?w($):a.raf($))},v=t=>{for(let e=0;e<t.length;e++)try{t[e](performance.now())}catch(t){s(t)}t.length=0},$=()=>{v(m),v(b),(h=m.length>0)&&a.raf($)},w=t=>Promise.resolve(undefined).then(t),g=y(b,!0),j=t=>{const e=new URL(t,a.u);return e.origin!==c.location.origin?e.href:e.pathname},O=t=>a.u=t;function S(){const t=this.attachShadow({mode:"open"});void 0===e&&(e=null),e&&(p?t.adoptedStyleSheets.push(e):t.adoptedStyleSheets=[...t.adoptedStyleSheets,e])}var k,M=new WeakMap,C=t=>"sc-"+t.p,E=t=>"object"==(t=typeof t)||"function"===t,A=(t,e,...n)=>{let l=null,o=null,s=!1,i=!1;const r=[],c=e=>{for(let n=0;n<e.length;n++)l=e[n],Array.isArray(l)?c(l):null!=l&&"boolean"!=typeof l&&((s="function"!=typeof t&&!E(l))&&(l=String(l)),s&&i?r[r.length-1].h+=l:r.push(s?x(null,l):l),i=s)};if(c(n),e){e.key&&(o=e.key);{const t=e.className||e.class;t&&(e.class="object"!=typeof t?t:Object.keys(t).filter((e=>t[e])).join(" "))}}if("function"==typeof t)return t(null===e?{}:e,r,D);const u=x(t,null);return u.m=e,r.length>0&&(u.v=r),u.$=o,u},x=(t,e)=>({i:0,j:t,h:null!=e?e:null,O:null,v:null,m:null,$:null}),R={},D={forEach:(t,e)=>t.map(L).forEach(e),map:(t,e)=>t.map(L).map(e).map(N)},L=t=>({vattrs:t.m,vchildren:t.v,vkey:t.$,vname:t.S,vtag:t.j,vtext:t.h}),N=t=>{if("function"==typeof t.vtag){const e={...t.vattrs};return t.vkey&&(e.key=t.vkey),t.vname&&(e.name=t.vname),A(t.vtag,e,...t.vchildren||[])}const e=x(t.vtag,t.vtext);return e.m=t.vattrs,e.v=t.vchildren,e.$=t.vkey,e.S=t.vname,e},_=(t,e,n)=>null==t||E(t)?t:4&e?(n&&"string"==typeof t||"false"!==t)&&(""===t||!!t):2&e?"string"==typeof t?parseFloat(t):"number"==typeof t?t:NaN:1&e?String(t):t,H=(t,e)=>{const n=t;return{emit:t=>P(n,e,{bubbles:!0,composed:!0,cancelable:!0,detail:t})}},P=(t,e,n)=>{const l=a.ce(e,n);return t.dispatchEvent(l),l},U=(t,e,n,s,i,r)=>{if(n===s)return;let u=o(t,e),f=e.toLowerCase();if("class"===e){const e=t.classList,l=W(n);let o=W(s);e.remove(...l.filter((t=>t&&!o.includes(t)))),e.add(...o.filter((t=>t&&!l.includes(t))))}else if("style"===e){for(const e in n)s&&null!=s[e]||(e.includes("-")?t.style.removeProperty(e):t.style[e]="");for(const e in s)n&&s[e]===n[e]||(e.includes("-")?t.style.setProperty(e,s[e]):t.style[e]=s[e])}else if("key"===e);else if(t.__lookupSetter__(e)||"o"!==e[0]||"n"!==e[1]){if("a"===e[0]&&e.startsWith("attr:")){const n=e.slice(5);let o;{const e=l(t);if(e&&e.l&&e.l.t){const t=e.l.t[n];t&&t[1]&&(o=t[1])}}return o||(o=n.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()),void(null==s||!1===s?!1===s&&""!==t.getAttribute(o)||t.removeAttribute(o):t.setAttribute(o,!0===s?"":s))}if("p"===e[0]&&e.startsWith("prop:")){const n=e.slice(5);try{t[n]=s}catch(t){}return}{const l=E(s);if((u||l&&null!==s)&&!i)try{if(t.tagName.includes("-"))t[e]!==s&&(t[e]=s);else{const l=null==s?"":s;"list"===e?u=!1:null!=n&&t[e]===l||("function"==typeof t.__lookupSetter__(e)?t[e]=l:t.setAttribute(e,l))}}catch(t){}null==s||!1===s?!1===s&&""!==t.getAttribute(e)||t.removeAttribute(e):(!u||4&r||i)&&!l&&1===t.nodeType&&t.setAttribute(e,s=!0===s?"":s)}}else if(e="-"===e[2]?e.slice(3):o(c,f)?f.slice(2):f[2]+e.slice(3),n||s){const l=e.endsWith(V);e=e.replace(q,""),n&&a.rel(t,e,n,l),s&&a.ael(t,e,s,l)}},F=/\s/,W=t=>("object"==typeof t&&t&&"baseVal"in t&&(t=t.baseVal),t&&"string"==typeof t?t.split(F):[]),V="Capture",q=new RegExp(V+"$"),z=(t,e,n)=>{const l=11===e.O.nodeType&&e.O.host?e.O.host:e.O,o=t&&t.m||{},s=e.m||{};for(const t of T(Object.keys(o)))t in s||U(l,t,o[t],void 0,n,e.i);for(const t of T(Object.keys(s)))U(l,t,o[t],s[t],n,e.i)};function T(t){return t.includes("ref")?[...t.filter((t=>"ref"!==t)),"ref"]:t}var Y=!1,Z=!1,B=(t,e,n)=>{const l=e.v[n];let o,s,i=0;if(null!=l.h)o=l.O=c.document.createTextNode(l.h);else{if(!c.document)throw new Error("You are trying to render a Stencil component in an environment that doesn't support the DOM.");if(o=l.O=c.document.createElement(l.j),z(null,l,Z),l.v){const e="template"===l.j?o.content:o;for(i=0;i<l.v.length;++i)s=B(t,l,i),s&&e.appendChild(s)}}return o["s-hn"]=k,o},G=(t,e,n,l,o,s)=>{let i,r=t;for(r.shadowRoot&&r.tagName===k&&(r=r.shadowRoot),"template"===n.j&&(r=r.content);o<=s;++o)l[o]&&(i=B(null,n,o),i&&(l[o].O=i,Q(r,i,e)))},I=(t,e,n)=>{for(let l=e;l<=n;++l){const e=t[l];if(e){const t=e.O;t&&t.remove()}}},J=(t,e,n=!1)=>t.j===e.j&&(n?(n&&!t.$&&e.$&&(t.$=e.$),!0):t.$===e.$),K=(t,e,n=!1)=>{const l=e.O=t.O,o=t.v,s=e.v,i=e.h;null==i?("slot"!==e.j||Y||t.S!==e.S&&(e.O["s-sn"]=e.S||"",(t=>{a.i|=1;const e=t.closest(k.toLowerCase());if(null!=e){const n=Array.from(e.__childNodes||e.childNodes).find((t=>t["s-cr"])),l=Array.from(t.__childNodes||t.childNodes);for(const t of n?l.reverse():l)null!=t["s-sh"]&&(Q(e,t,null!=n?n:null),t["s-sh"]=void 0)}a.i&=-2})(e.O.parentElement)),z(t,e,Z),null!==o&&null!==s?((t,e,n,l,o=!1)=>{let s,i,r=0,c=0,u=0,a=0,f=e.length-1,d=e[0],p=e[f],h=l.length-1,m=l[0],b=l[h];const y="template"===n.j?t.content:t;for(;r<=f&&c<=h;)if(null==d)d=e[++r];else if(null==p)p=e[--f];else if(null==m)m=l[++c];else if(null==b)b=l[--h];else if(J(d,m,o))K(d,m,o),d=e[++r],m=l[++c];else if(J(p,b,o))K(p,b,o),p=e[--f],b=l[--h];else if(J(d,b,o))K(d,b,o),Q(y,d.O,p.O.nextSibling),d=e[++r],b=l[--h];else if(J(p,m,o))K(p,m,o),Q(y,p.O,d.O),p=e[--f],m=l[++c];else{for(u=-1,a=r;a<=f;++a)if(e[a]&&null!==e[a].$&&e[a].$===m.$){u=a;break}u>=0?(i=e[u],i.j!==m.j?s=B(e&&e[c],n,u):(K(i,m,o),e[u]=void 0,s=i.O),m=l[++c]):(s=B(e&&e[c],n,c),m=l[++c]),s&&Q(d.O.parentNode,s,d.O)}r>f?G(t,null==l[h+1]?null:l[h+1].O,n,l,c,h):c>h&&I(e,r,f)})(l,o,e,s,n):null!==s?(null!==t.h&&(l.textContent=""),G(l,null,e,s,0,s.length-1)):!n&&null!==o&&I(o,0,o.length-1)):t.h!==i&&(l.data=i)},Q=(t,e,n)=>t.__insertBefore?t.__insertBefore(e,n):null==t?void 0:t.insertBefore(e,n),X=(t,e,n=!1)=>{const l=t.$hostElement$,o=t.l,s=t.k||x(null,null);var i;const r=(i=e)&&i.j===R?e:A(null,null,e);if(k=l.tagName,o.M&&(r.m=r.m||{},o.M.forEach((([t,e])=>{r.m[e]=l[t]}))),n&&r.m)for(const t of Object.keys(r.m))l.hasAttribute(t)&&!["key","ref","style","class"].includes(t)&&(r.m[t]=l[t]);r.j=null,r.i|=4,t.k=r,r.O=s.O=l.shadowRoot||l,Y=!(!(1&o.i)||128&o.i),K(s,r,n)},tt=(t,e)=>{if(e&&!t.C&&e["s-p"]){const n=e["s-p"].push(new Promise((l=>t.C=()=>{e["s-p"].splice(n-1,1),l()})))}},et=(t,e)=>{if(t.i|=16,4&t.i)return void(t.i|=512);tt(t,t.A);const n=()=>nt(t,e);if(!e)return g(n);queueMicrotask((()=>{n()}))},nt=(t,e)=>{const n=t.$hostElement$,l=n;if(!l)throw new Error(`Can't render component <${n.tagName.toLowerCase()} /> with invalid Stencil runtime! Make sure this imported component is compiled with a \`externalRuntime: true\` flag. For more information, please refer to https://stenciljs.com/docs/custom-elements#externalruntime`);let o;return o=ut(l,e?"componentWillLoad":"componentWillUpdate",void 0,n),o=lt(o,(()=>ut(l,"componentWillRender",void 0,n))),lt(o,(()=>st(t,l,e)))},lt=(t,e)=>ot(t)?t.then(e).catch((t=>{console.error(t),e()})):e(),ot=t=>t instanceof Promise||t&&t.then&&"function"==typeof t.then,st=async(t,e,n)=>{var l;const o=t.$hostElement$,s=o["s-rc"];n&&(t=>{const e=t.l,n=t.$hostElement$,l=e.i,o=((t,e)=>{var n,l,o;const s=C(e),r=i.get(s);if(!c.document)return s;if(t=11===t.nodeType?t:c.document,r)if("string"==typeof r){let o,i=M.get(t=t.head||t);if(i||M.set(t,i=new Set),!i.has(s)){o=c.document.createElement("style"),o.textContent=r;const u=null!=(n=a.R)?n:function(){var t,e,n;return null!=(n=null==(e=null==(t=c.document.head)?void 0:t.querySelector('meta[name="csp-nonce"]'))?void 0:e.getAttribute("content"))?n:void 0}();if(null!=u&&o.setAttribute("nonce",u),!(1&e.i))if("HEAD"===t.nodeName){const e=t.querySelectorAll("link[rel=preconnect]"),n=e.length>0?e[e.length-1].nextSibling:t.querySelector("style");t.insertBefore(o,(null==n?void 0:n.parentNode)===t?n:null)}else if("host"in t)if(d){const e=new(null!=(l=t.defaultView)?l:t.ownerDocument.defaultView).CSSStyleSheet;e.replaceSync(r),p?t.adoptedStyleSheets.unshift(e):t.adoptedStyleSheets=[e,...t.adoptedStyleSheets]}else{const e=t.querySelector("style");e?e.textContent=r+e.textContent:t.prepend(o)}else t.append(o);1&e.i&&t.insertBefore(o,null),4&e.i&&(o.textContent+="slot-fb{display:contents}slot-fb[hidden]{display:none}"),i&&i.add(s)}}else{let e=M.get(t);if(e||M.set(t,e=new Set),!e.has(s)){const n=null!=(o=t.defaultView)?o:t.ownerDocument.defaultView;let l;if(r.constructor===n.CSSStyleSheet)l=r;else{l=new n.CSSStyleSheet;for(let t=0;t<r.cssRules.length;t++)l.insertRule(r.cssRules[t].cssText,t)}p?t.adoptedStyleSheets.push(l):t.adoptedStyleSheets=[...t.adoptedStyleSheets,l],e.add(s)}}return s})(n.shadowRoot?n.shadowRoot:n.getRootNode(),e);10&l&&(n["s-sc"]=o,n.classList.add(o+"-h"))})(t);it(t,e,o,n),s&&(s.map((t=>t())),o["s-rc"]=void 0);{const e=null!=(l=o["s-p"])?l:[],n=()=>rt(t);0===e.length?n():(Promise.all(e).then(n).catch(n),t.i|=4,e.length=0)}},it=(t,e,n,l)=>{try{e=e.render(),t.i&=-17,t.i|=2,X(t,e,l)}catch(e){s(e,t.$hostElement$)}return null},rt=t=>{const e=t.$hostElement$,n=e,l=t.A;ut(n,"componentDidRender",void 0,e),64&t.i?ut(n,"componentDidUpdate",void 0,e):(t.i|=64,at(e),ut(n,"componentDidLoad",void 0,e),t.D(e),l||ct()),t.C&&(t.C(),t.C=void 0),512&t.i&&w((()=>et(t,!1))),t.i&=-517},ct=()=>{w((()=>P(c,"appload",{detail:{namespace:"pixel"}})))},ut=(t,e,n,l)=>{if(t&&t[e])try{return t[e](n)}catch(t){s(t,l)}},at=t=>t.classList.add("hydrated"),ft=(t,e,n,o)=>{const i=l(t);if(!i)return;const r=t,c=i.o.get(e),u=i.i,a=r;n=_(n,o.t[e][0],!!(64&o.i));const f=Number.isNaN(c)&&Number.isNaN(n);if(n!==c&&!f){if(i.o.set(e,n),o.L){const t=o.L[e];t&&t.map((t=>{try{const[[l,o]]=Object.entries(t);(128&u||1&o)&&(a?a[l](n,c,e):i.N.push((()=>{i._[l](n,c,e)})))}catch(t){s(t,r)}}))}if(2&u){if(a.componentShouldUpdate&&!1===a.componentShouldUpdate(n,c,e)&&!(16&u))return;16&u||et(i,!1)}}},dt=(e,n,o)=>{var s,i;const c=e.prototype;64&n.i&&1&o&&r.forEach((t=>{const e=c[t];Object.defineProperty(c,t,{value(...n){var o;const s=l(this),i=this;i?"function"==typeof e&&e.call(i,...n):null==(o=null==s?void 0:s.H)||o.then((e=>{const l=e[t];"function"==typeof l&&l.call(e,...n)}))}})}));{e.watchers&&!n.L&&(n.L=e.watchers),e.deserializers&&!n.P&&(n.P=e.deserializers),e.serializers&&!n.U&&(n.U=e.serializers);const o=Object.entries(null!=(s=n.t)?s:{});o.map((([e,[o]])=>{if(31&o||32&o){const{get:s,set:i}=t(c,e)||{};s&&(n.t[e][0]|=2048),i&&(n.t[e][0]|=4096),Object.defineProperty(c,e,{get(){return s?s.apply(this):(t=e,l(this).o.get(t));var t},configurable:!0,enumerable:!0}),Object.defineProperty(c,e,{set(t){const s=l(this);if(s){if(i)return void 0===(32&o?this[e]:s.$hostElement$[e])&&s.o.get(e)&&(t=s.o.get(e)),i.apply(this,[_(t,o,!!(64&n.i))]),void ft(this,e,t=32&o?this[e]:s.$hostElement$[e],n);ft(this,e,t,n)}}})}}));{const t=new Map;c.attributeChangedCallback=function(e,s,i){a.jmp((()=>{var r;const u=t.get(e),a=l(this);if(this.hasOwnProperty(u),c.hasOwnProperty(u)&&"number"==typeof this[u]&&this[u]==i)return;if(null==u){const t=null==a?void 0:a.i;if(a&&t&&!(8&t)&&i!==s){const l=this,o=null==(r=n.L)?void 0:r[e];null==o||o.forEach((n=>{const[[o,r]]=Object.entries(n);null!=l[o]&&(128&t||1&r)&&l[o].call(l,i,s,e)}))}return}const f=o.find((([t])=>t===u));f&&4&f[1][0]&&(i=null!==i&&"false"!==i);const d=Object.getOwnPropertyDescriptor(c,u);i==this[u]||d.get&&!d.set||(this[u]=i)}))},e.observedAttributes=Array.from(new Set([...Object.keys(null!=(i=n.L)?i:{}),...o.filter((([t,e])=>31&e[0])).map((([e,l])=>{var o;const s=l[1]||e;return t.set(s,e),512&l[0]&&(null==(o=n.M)||o.push([e,s])),s}))]))}}return e},pt=(t,e)=>{const o={i:e[0],p:e[1]};try{o.t=e[2],o.F=e[3],o.L=t.L,o.P=t.P,o.U=t.U,o.M=[];const r=t.prototype.connectedCallback,c=t.prototype.disconnectedCallback;return Object.assign(t.prototype,{__hasHostListenerAttached:!1,__registerHost(){((t,e)=>{const l={i:0,$hostElement$:t,l:e,o:new Map,W:new Map};l.H=new Promise((t=>l.D=t)),t["s-p"]=[],t["s-rc"]=[];const o=l;t.__stencil__getHostRef=()=>o,512&e.i&&n(t,l)})(this,o)},connectedCallback(){if(!this.__hasHostListenerAttached){const t=l(this);if(!t)return;mt(this,t,o.F),this.__hasHostListenerAttached=!0}(t=>{if(!(1&a.i)){const e=l(t);if(!e)return;const n=e.l,o=()=>{};if(1&e.i)mt(t,e,n.F),(null==e?void 0:e._)||(null==e?void 0:e.H)&&e.H.then((()=>{}));else{e.i|=1;{let n=t;for(;n=n.parentNode||n.host;)if(n["s-p"]){tt(e,e.A=n);break}}n.t&&Object.entries(n.t).map((([e,[n]])=>{if(31&n&&Object.prototype.hasOwnProperty.call(t,e)){const n=t[e];delete t[e],t[e]=n}})),(async(t,e,n)=>{let l;try{if(!(32&e.i)&&(e.i|=32,l=t.constructor,customElements.whenDefined(t.localName).then((()=>e.i|=128)),l&&l.style)){let t;"string"==typeof l.style&&(t=l.style);const e=C(n);if(!i.has(e)){const l=()=>{};((t,e,n)=>{let l=i.get(t);d&&n?(l=l||new CSSStyleSheet,"string"==typeof l?l=e:l.replaceSync(e)):l=e,i.set(t,l)})(e,t,!!(1&n.i)),l()}}const o=e.A,s=()=>et(e,!0);o&&o["s-rc"]?o["s-rc"].push(s):s()}catch(n){s(n,t),e.C&&(e.C(),e.C=void 0),e.D&&e.D(t)}})(t,e,n)}o()}})(this),r&&r.call(this)},disconnectedCallback(){(async t=>{if(!(1&a.i)){const e=l(t);(null==e?void 0:e.V)&&(e.V.map((t=>t())),e.V=void 0)}M.has(t)&&M.delete(t),t.shadowRoot&&M.has(t.shadowRoot)&&M.delete(t.shadowRoot)})(this),c&&c.call(this)},__attachShadow(){if(this.shadowRoot){if("open"!==this.shadowRoot.mode)throw new Error(`Unable to re-use existing shadow root for ${o.p}! Mode is set to ${this.shadowRoot.mode} but Stencil only supports open shadow roots.`)}else S.call(this,o)}}),Object.defineProperty(t,"is",{value:o.p,configurable:!0}),dt(t,o,3)}catch(e){return s(e),t}},ht=(t,e)=>e,mt=(t,e,n)=>{n&&c.document&&n.map((([n,l,o])=>{const s=t,i=bt(e,o),r=yt(n);a.ael(s,l,i,r),(e.V=e.V||[]).push((()=>a.rel(s,l,i,r)))}))},bt=(t,e)=>n=>{try{t.$hostElement$[e](n)}catch(e){s(e,t.$hostElement$)}},yt=t=>f?{passive:!!(1&t),capture:!!(2&t)}:!!(2&t),vt=t=>a.R=t,$t=t=>Object.assign(a,t);function wt(t,e){X({l:{i:0,p:e.tagName},$hostElement$:e},t)}function gt(t){return t}export{ht as F,u as H,vt as a,$t as b,H as c,j as g,A as h,pt as p,wt as r,O as s,gt as t}
@@ -0,0 +1 @@
1
+ import{t as i,p as t,H as e,c as o,h as s}from"./p-BWyvzXuA.js";let a=0;const r=t(class extends e{constructor(i){super(),!1!==i&&this.__registerHost(),this.__attachShadow(),this.tooltipShow=o(this,"show"),this.tooltipHide=o(this,"hide"),this.position="top",this.size="medium",this.delay=300,this.visible=!1,this.disabled=!1,this.arrow=!0,this.maxWidth="300px",this.isActive=!1,this.tooltipId="ip-tooltip-"+a++,this.delayTimer=null,this.hideTimer=null,this.clearTimers=()=>{null!==this.delayTimer&&(clearTimeout(this.delayTimer),this.delayTimer=null),null!==this.hideTimer&&(clearTimeout(this.hideTimer),this.hideTimer=null)},this.setActive=i=>{const t=this.isTooltipVisible;this.isActive=i;const e=this.isTooltipVisible;!t&&e&&(document.addEventListener("keydown",this.handleKeyDown),this.tooltipShow.emit()),t&&!e&&(document.removeEventListener("keydown",this.handleKeyDown),this.tooltipHide.emit())},this.handleTriggerMouseEnter=()=>{this.disabled||(this.clearTimers(),this.delayTimer=setTimeout((()=>{this.setActive(!0)}),this.delay))},this.handleTriggerMouseLeave=()=>{this.clearTimers(),this.hideTimer=setTimeout((()=>{this.setActive(!1)}),100)},this.handleTooltipMouseEnter=()=>{this.clearTimers()},this.handleTooltipMouseLeave=()=>{this.clearTimers(),this.hideTimer=setTimeout((()=>{this.setActive(!1)}),100)},this.handleKeyDown=i=>{"Escape"===i.key&&this.isTooltipVisible&&(this.clearTimers(),this.setActive(!1))}}onVisibleChange(i,t){const e=t||this.isActive,o=i||this.isActive;!e&&o&&this.tooltipShow.emit(),e&&!o&&this.tooltipHide.emit()}onDisabledChange(i){i&&(this.clearTimers(),this.setActive(!1))}disconnectedCallback(){this.clearTimers(),document.removeEventListener("keydown",this.handleKeyDown)}get isTooltipVisible(){return this.visible||this.isActive}handleFocusin(){this.disabled||(this.clearTimers(),this.setActive(!0))}handleFocusout(){this.clearTimers(),this.setActive(!1)}render(){const i=this.isTooltipVisible,t=["ip-tooltip__bubble",`ip-tooltip__bubble--${this.position}`,`ip-tooltip__bubble--${this.size}`,i&&"ip-tooltip__bubble--visible",this.arrow&&"ip-tooltip__bubble--arrow"].filter(Boolean).join(" ");return s("div",{key:"5112747e6a9ac899c3f951bbe63be3c478bf9a88",class:"ip-tooltip"},s("div",{key:"022b7afa2a94a134933ea40ae4423a25899c928b",class:"ip-tooltip__trigger","aria-describedby":i?this.tooltipId:void 0,onMouseEnter:this.handleTriggerMouseEnter,onMouseLeave:this.handleTriggerMouseLeave},s("slot",{key:"d74376a3c8433844847286b2747e0d71bc157841",name:"trigger"})),s("div",{key:"6374a6561ce1e2b2e62877dca0be7907aacc16a4",id:this.tooltipId,role:"tooltip",class:t,"aria-hidden":i?"false":"true",style:{maxWidth:this.maxWidth},onMouseEnter:this.handleTooltipMouseEnter,onMouseLeave:this.handleTooltipMouseLeave},s("slot",{key:"c06978dc6a2fd29bff8c5846592554f1be606b89"})))}static get watchers(){return{visible:[{onVisibleChange:0}],disabled:[{onDisabledChange:0}]}}static get style(){return':host{display:inline-block}.ip-tooltip{position:relative;display:inline-block}.ip-tooltip__trigger{display:inline-block}.ip-tooltip__bubble{position:absolute;z-index:1000;width:max-content;background-color:var(--ip_color_surface_primary_inverse);color:var(--ip_color_text_primary_black_inverse);border-radius:var(--ip_radius_size_medium);font-family:var(--ip_typography_font_family_primary);line-height:var(--ip_typography_body_line_height_default);word-wrap:break-word;white-space:normal;pointer-events:none;opacity:0;visibility:hidden;transition:opacity 150ms ease-in-out, visibility 150ms ease-in-out}.ip-tooltip__bubble--visible{opacity:1;visibility:visible;pointer-events:auto}.ip-tooltip__bubble--small{padding:var(--ip_spacing_space_050) var(--ip_spacing_space_075);font-size:var(--ip_typography_body_font_size_small)}.ip-tooltip__bubble--medium{padding:var(--ip_spacing_space_075) var(--ip_spacing_space_100);font-size:var(--ip_typography_body_font_size_medium)}.ip-tooltip__bubble--large{padding:var(--ip_spacing_space_100) var(--ip_spacing_space_150);font-size:var(--ip_typography_body_font_size_large)}.ip-tooltip__bubble--top{bottom:calc(100% + var(--ip_spacing_space_100));left:50%;transform:translateX(-50%)}.ip-tooltip__bubble--bottom{top:calc(100% + var(--ip_spacing_space_100));left:50%;transform:translateX(-50%)}.ip-tooltip__bubble--left{right:calc(100% + var(--ip_spacing_space_100));top:50%;transform:translateY(-50%)}.ip-tooltip__bubble--right{left:calc(100% + var(--ip_spacing_space_100));top:50%;transform:translateY(-50%)}.ip-tooltip__bubble--arrow::after{content:"";position:absolute;width:0;height:0;border:6px solid transparent}.ip-tooltip__bubble--arrow.ip-tooltip__bubble--top::after{top:100%;left:50%;transform:translateX(-50%);border-top-color:var(--ip_color_surface_primary_inverse)}.ip-tooltip__bubble--arrow.ip-tooltip__bubble--bottom::after{bottom:100%;left:50%;transform:translateX(-50%);border-bottom-color:var(--ip_color_surface_primary_inverse)}.ip-tooltip__bubble--arrow.ip-tooltip__bubble--left::after{left:100%;top:50%;transform:translateY(-50%);border-left-color:var(--ip_color_surface_primary_inverse)}.ip-tooltip__bubble--arrow.ip-tooltip__bubble--right::after{right:100%;top:50%;transform:translateY(-50%);border-right-color:var(--ip_color_surface_primary_inverse)}'}},[257,"ip-tooltip",{position:[513],size:[513],delay:[514],visible:[516],disabled:[516],arrow:[516],maxWidth:[513,"max-width"],isActive:[32]},[[0,"focusin","handleFocusin"],[0,"focusout","handleFocusout"]],{visible:[{onVisibleChange:0}],disabled:[{onDisabledChange:0}]}]);function l(){"undefined"!=typeof customElements&&["ip-tooltip"].forEach((t=>{"ip-tooltip"===t&&(customElements.get(i(t))||customElements.define(i(t),r))}))}l();export{r as I,l as d}
@@ -0,0 +1 @@
1
+ import{t,p as o,H as i,h as r,F as a}from"./p-BWyvzXuA.js";const e=o(class extends i{constructor(t){super(),!1!==t&&this.__registerHost(),this.__attachShadow(),this.internals=this.attachInternals(),this.ariaLabel=null,this.hasLabel=!1,this.variant="primary",this.loading=!1,this.disabled=!1,this.type="submit",this.size="medium",this.alignIcon="start",this.onLabelSlotChange=t=>{this.hasLabel=t.target.assignedNodes({flatten:!0}).length>0},this.handleClick=()=>"submit"===this.type?this.internals.form?.requestSubmit():"reset"===this.type?this.internals.form?.reset():void 0}render(){const t=this.disabled||this.loading;return r("button",{key:"4a68c0b460830d7911d60ad86b2172285bceab7d",class:`ip-button ip-button--${this.variant} ip-button--${this.size}`,type:"button",disabled:t,"aria-disabled":t?"true":"false","aria-busy":this.loading?"true":"false","aria-label":this.ariaLabel??void 0,onClick:this.handleClick},"start"===this.alignIcon&&r("slot",{key:"icon-start",name:"icon"}),this.hasLabel?r("span",{class:`ip-button__label ip-button__label--${this.size}`},r("slot",{onSlotchange:this.onLabelSlotChange})):r("slot",{onSlotchange:this.onLabelSlotChange}),"end"===this.alignIcon&&r("slot",{key:"icon-end",name:"icon"}),this.loading&&r(a,{key:"462d4ff5ac74f09eed3ed3ce2994cc1dbc6d1455"},r("span",{key:"d9664011f384cb50de4d1dfbddbc8f08b9c185c6",class:"ip-button__spinner","aria-hidden":"true"}),r("span",{key:"8eb6fa93ef8f799026e80462d9df81fe7e5dd637",class:"ip-button__sr-only"},"Loading...")))}static get formAssociated(){return!0}static get style(){return".ip-button{border:none;border-radius:var(--ip_radius_size_medium);margin:0;cursor:pointer;position:relative;overflow:hidden;display:inline-flex;align-items:center;justify-content:center;font-family:var(--ip_typography_font_family_primary);transition:background-color 150ms ease-in-out, color 150ms ease-in-out}.ip-button:disabled{cursor:not-allowed}.ip-button:focus-visible{outline:2px solid var(--ip_color_button_focus_default);outline-offset:2px}.ip-button--small{padding:var(--ip_spacing_space_100) var(--ip_spacing_space_150);gap:var(--ip_spacing_space_125);font-size:var(--ip_typography_body_font_size_small)}.ip-button--medium{padding:var(--ip_spacing_space_125) var(--ip_spacing_space_200);gap:var(--ip_spacing_space_150);font-size:var(--ip_typography_body_font_size_medium)}.ip-button--large{padding:var(--ip_spacing_space_150) var(--ip_spacing_space_250);gap:var(--ip_spacing_space_200);font-size:var(--ip_typography_body_font_size_large)}.ip-button--primary{background-color:var(--ip_color_button_background_primary_default);color:var(--ip_color_button_text_primary_default)}.ip-button--primary:hover:not(:disabled){background-color:var(--ip_color_button_background_primary_hover)}.ip-button--primary:active:not(:disabled){background-color:var(--ip_color_button_background_primary_active)}.ip-button--primary:disabled{background-color:var(--ip_color_button_background_primary_disabled);color:var(--ip_color_button_text_primary_disabled)}.ip-button--secondary{background-color:var(--ip_color_button_background_secondary_default);color:var(--ip_color_button_text_secondary_default)}.ip-button--secondary:hover:not(:disabled){background-color:var(--ip_color_button_background_secondary_hover)}.ip-button--secondary:active:not(:disabled){background-color:var(--ip_color_button_background_secondary_active)}.ip-button--secondary:disabled{background-color:var(--ip_color_button_background_secondary_disabled);color:var(--ip_color_button_text_secondary_disabled)}.ip-button--tertiary{background-color:var(--ip_color_button_background_tertiary_default);color:var(--ip_color_button_text_tertiary_default)}.ip-button--tertiary:hover:not(:disabled){background-color:var(--ip_color_button_background_tertiary_hover)}.ip-button--tertiary:active:not(:disabled){background-color:var(--ip_color_button_background_tertiary_active)}.ip-button--tertiary:disabled{background-color:var(--ip_color_button_background_tertiary_disabled);color:var(--ip_color_button_text_tertiary_disabled)}.ip-button--brand{background-color:var(--ip_color_button_background_brand_default);color:var(--ip_color_button_text_brand_default)}.ip-button--brand:hover:not(:disabled){background-color:var(--ip_color_button_background_brand_hover)}.ip-button--brand:active:not(:disabled){background-color:var(--ip_color_button_background_brand_active)}.ip-button--brand:disabled{background-color:var(--ip_color_button_background_brand_disabled);color:var(--ip_color_button_text_brand_disabled)}.ip-button--destructive{background-color:var(--ip_color_button_background_destructive_default);color:var(--ip_color_button_text_destructive_default)}.ip-button--destructive:hover:not(:disabled){background-color:var(--ip_color_button_background_destructive_hover)}.ip-button--destructive:active:not(:disabled){background-color:var(--ip_color_button_background_destructive_active)}.ip-button--destructive:disabled{background-color:var(--ip_color_button_background_destructive_disabled);color:var(--ip_color_button_text_destructive_disabled)}.ip-button__label{display:inline-flex;align-items:center}.ip-button__label--small{height:18px}.ip-button__label--medium{height:20px}.ip-button__label--large{height:22px}.ip-button__spinner{width:0.75em;height:0.75em;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:ip-button-spin 900ms linear infinite;flex-shrink:0}.ip-button__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}@keyframes ip-button-spin{to{transform:rotate(360deg)}}::slotted([slot=icon]){display:inline-flex !important;align-items:center;justify-content:center}:host([size=small]) ::slotted([slot=icon]){font-size:var(--ip_iconography_size_small);width:18px !important;height:18px !important}:host([size=medium]) ::slotted([slot=icon]){font-size:var(--ip_iconography_size_medium);width:20px !important;height:20px !important}:host([size=large]) ::slotted([slot=icon]){font-size:var(--ip_iconography_size_large);width:22px !important;height:22px !important}"}},[321,"ip-button",{ariaLabel:[1,"aria-label"],variant:[513],loading:[516],disabled:[516],type:[513],size:[513],alignIcon:[513,"align-icon"],hasLabel:[32]}]);function n(){"undefined"!=typeof customElements&&["ip-button"].forEach((o=>{"ip-button"===o&&(customElements.get(t(o))||customElements.define(t(o),e))}))}n();export{e as I,n as d}
@@ -1,10 +1,14 @@
1
- import { ChangeDetectorRef, ElementRef, NgZone } from '@angular/core';
1
+ import { ChangeDetectorRef, ElementRef, EventEmitter, NgZone } from '@angular/core';
2
2
  import type { Components } from '@norconsult-digital-public/isypixel/web-components/components';
3
3
  import * as i0 from "@angular/core";
4
4
  export declare class IpButton {
5
5
  protected z: NgZone;
6
6
  protected el: HTMLIpButtonElement;
7
7
  /**
8
+ * Accessible name forwarded to the inner <button>. Useful for icon-only usage, and when provided it overrides the accessible name derived from any slotted label text. @default null
9
+ */
10
+ set ariaLabel(_: Components.IpButton['ariaLabel']);
11
+ /**
8
12
  * Visual variant of the button @default 'primary'
9
13
  */
10
14
  set variant(_: Components.IpButton['variant']);
@@ -30,7 +34,54 @@ export declare class IpButton {
30
34
  set alignIcon(_: Components.IpButton['alignIcon']);
31
35
  constructor(c: ChangeDetectorRef, r: ElementRef, z: NgZone);
32
36
  static ɵfac: i0.ɵɵFactoryDeclaration<IpButton, never>;
33
- static ɵcmp: i0.ɵɵComponentDeclaration<IpButton, "ip-button", never, { "alignIcon": { "alias": "alignIcon"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "size": { "alias": "size"; "required": false; }; "type": { "alias": "type"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; }, {}, never, ["*"], true, never>;
37
+ static ɵcmp: i0.ɵɵComponentDeclaration<IpButton, "ip-button", never, { "alignIcon": { "alias": "alignIcon"; "required": false; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "size": { "alias": "size"; "required": false; }; "type": { "alias": "type"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; }, {}, never, ["*"], true, never>;
34
38
  }
35
39
  export declare interface IpButton extends Components.IpButton {
36
40
  }
41
+ export declare class IpTooltip {
42
+ protected z: NgZone;
43
+ protected el: HTMLIpTooltipElement;
44
+ /**
45
+ * Placement of the tooltip bubble relative to the trigger element. @default 'top'
46
+ */
47
+ set position(_: Components.IpTooltip['position']);
48
+ /**
49
+ * Visual size of the tooltip bubble. @default 'medium'
50
+ */
51
+ set size(_: Components.IpTooltip['size']);
52
+ /**
53
+ * Delay in milliseconds before the tooltip appears on hover. @default 300
54
+ */
55
+ set delay(_: Components.IpTooltip['delay']);
56
+ /**
57
+ * Forces the tooltip visible regardless of hover or focus state. @default false
58
+ */
59
+ set visible(_: Components.IpTooltip['visible']);
60
+ /**
61
+ * Prevents the tooltip from showing on hover or focus. @default false
62
+ */
63
+ set disabled(_: Components.IpTooltip['disabled']);
64
+ /**
65
+ * Renders a directional arrow pointing toward the trigger element. @default true
66
+ */
67
+ set arrow(_: Components.IpTooltip['arrow']);
68
+ /**
69
+ * Maximum width of the tooltip bubble. Use absolute or viewport units — percentage values are not supported as they resolve relative to the trigger element. E.g. "300px", "20rem", "50vw". @default '300px'
70
+ */
71
+ set maxWidth(_: Components.IpTooltip['maxWidth']);
72
+ show: EventEmitter<CustomEvent<void>>;
73
+ hide: EventEmitter<CustomEvent<void>>;
74
+ constructor(c: ChangeDetectorRef, r: ElementRef, z: NgZone);
75
+ static ɵfac: i0.ɵɵFactoryDeclaration<IpTooltip, never>;
76
+ static ɵcmp: i0.ɵɵComponentDeclaration<IpTooltip, "ip-tooltip", never, { "arrow": { "alias": "arrow"; "required": false; }; "delay": { "alias": "delay"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "maxWidth": { "alias": "maxWidth"; "required": false; }; "position": { "alias": "position"; "required": false; }; "size": { "alias": "size"; "required": false; }; "visible": { "alias": "visible"; "required": false; }; }, { "show": "show"; "hide": "hide"; }, never, ["*"], true, never>;
77
+ }
78
+ export declare interface IpTooltip extends Components.IpTooltip {
79
+ /**
80
+ * Emitted when the tooltip transitions from hidden to visible.
81
+ */
82
+ show: EventEmitter<CustomEvent<void>>;
83
+ /**
84
+ * Emitted when the tooltip transitions from visible to hidden.
85
+ */
86
+ hide: EventEmitter<CustomEvent<void>>;
87
+ }
@@ -6,14 +6,20 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  /* tslint:disable */
8
8
  /* auto-generated angular directive proxies */
9
- import { ChangeDetectionStrategy, Component } from '@angular/core';
9
+ import { ChangeDetectionStrategy, Component, EventEmitter, Output } from '@angular/core';
10
10
  import { ProxyCmp } from './angular-component-lib/utils';
11
11
  import { defineCustomElement as defineIpButton } from '@norconsult-digital-public/isypixel/web-components/components/ip-button.js';
12
+ import { defineCustomElement as defineIpTooltip } from '@norconsult-digital-public/isypixel/web-components/components/ip-tooltip.js';
12
13
  import * as i0 from "@angular/core";
13
14
  let IpButton = class IpButton {
14
15
  z;
15
16
  el;
16
17
  /**
18
+ * Accessible name forwarded to the inner <button>. Useful for icon-only usage, and when provided it overrides the accessible name derived from any slotted label text. @default null
19
+ */
20
+ set ariaLabel(_) { }
21
+ ;
22
+ /**
17
23
  * Visual variant of the button @default 'primary'
18
24
  */
19
25
  set variant(_) { }
@@ -49,12 +55,12 @@ let IpButton = class IpButton {
49
55
  this.el = r.nativeElement;
50
56
  }
51
57
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: IpButton, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
52
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: IpButton, isStandalone: true, selector: "ip-button", inputs: { alignIcon: "alignIcon", disabled: "disabled", loading: "loading", size: "size", type: "type", variant: "variant" }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
58
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: IpButton, isStandalone: true, selector: "ip-button", inputs: { alignIcon: "alignIcon", ariaLabel: "ariaLabel", disabled: "disabled", loading: "loading", size: "size", type: "type", variant: "variant" }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
53
59
  };
54
60
  IpButton = __decorate([
55
61
  ProxyCmp({
56
62
  defineCustomElementFn: defineIpButton,
57
- inputs: ['alignIcon', 'disabled', 'loading', 'size', 'type', 'variant']
63
+ inputs: ['alignIcon', 'ariaLabel', 'disabled', 'loading', 'size', 'type', 'variant']
58
64
  })
59
65
  ], IpButton);
60
66
  export { IpButton };
@@ -65,6 +71,76 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
65
71
  changeDetection: ChangeDetectionStrategy.OnPush,
66
72
  template: '<ng-content></ng-content>',
67
73
  // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
68
- inputs: ['alignIcon', 'disabled', 'loading', 'size', 'type', 'variant'],
74
+ inputs: ['alignIcon', 'ariaLabel', 'disabled', 'loading', 'size', 'type', 'variant'],
69
75
  }]
70
76
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i0.NgZone }] });
77
+ let IpTooltip = class IpTooltip {
78
+ z;
79
+ el;
80
+ /**
81
+ * Placement of the tooltip bubble relative to the trigger element. @default 'top'
82
+ */
83
+ set position(_) { }
84
+ ;
85
+ /**
86
+ * Visual size of the tooltip bubble. @default 'medium'
87
+ */
88
+ set size(_) { }
89
+ ;
90
+ /**
91
+ * Delay in milliseconds before the tooltip appears on hover. @default 300
92
+ */
93
+ set delay(_) { }
94
+ ;
95
+ /**
96
+ * Forces the tooltip visible regardless of hover or focus state. @default false
97
+ */
98
+ set visible(_) { }
99
+ ;
100
+ /**
101
+ * Prevents the tooltip from showing on hover or focus. @default false
102
+ */
103
+ set disabled(_) { }
104
+ ;
105
+ /**
106
+ * Renders a directional arrow pointing toward the trigger element. @default true
107
+ */
108
+ set arrow(_) { }
109
+ ;
110
+ /**
111
+ * Maximum width of the tooltip bubble. Use absolute or viewport units — percentage values are not supported as they resolve relative to the trigger element. E.g. "300px", "20rem", "50vw". @default '300px'
112
+ */
113
+ set maxWidth(_) { }
114
+ ;
115
+ show = new EventEmitter();
116
+ hide = new EventEmitter();
117
+ constructor(c, r, z) {
118
+ this.z = z;
119
+ c.detach();
120
+ this.el = r.nativeElement;
121
+ }
122
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: IpTooltip, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
123
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: IpTooltip, isStandalone: true, selector: "ip-tooltip", inputs: { arrow: "arrow", delay: "delay", disabled: "disabled", maxWidth: "maxWidth", position: "position", size: "size", visible: "visible" }, outputs: { show: "show", hide: "hide" }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
124
+ };
125
+ IpTooltip = __decorate([
126
+ ProxyCmp({
127
+ defineCustomElementFn: defineIpTooltip,
128
+ inputs: ['arrow', 'delay', 'disabled', 'maxWidth', 'position', 'size', 'visible']
129
+ })
130
+ ], IpTooltip);
131
+ export { IpTooltip };
132
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: IpTooltip, decorators: [{
133
+ type: Component,
134
+ args: [{
135
+ selector: 'ip-tooltip',
136
+ changeDetection: ChangeDetectionStrategy.OnPush,
137
+ template: '<ng-content></ng-content>',
138
+ // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
139
+ inputs: ['arrow', 'delay', 'disabled', 'maxWidth', 'position', 'size', 'visible'],
140
+ outputs: ['show', 'hide'],
141
+ }]
142
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i0.NgZone }], propDecorators: { show: [{
143
+ type: Output
144
+ }], hide: [{
145
+ type: Output
146
+ }] } });
@@ -1,26 +1,31 @@
1
1
  /* tslint:disable */
2
2
  /* auto-generated angular directive proxies */
3
- import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone } from '@angular/core';
3
+ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Output, NgZone } from '@angular/core';
4
4
 
5
5
  import { ProxyCmp } from './angular-component-lib/utils';
6
6
 
7
7
  import type { Components } from '@norconsult-digital-public/isypixel/web-components/components';
8
8
 
9
9
  import { defineCustomElement as defineIpButton } from '@norconsult-digital-public/isypixel/web-components/components/ip-button.js';
10
+ import { defineCustomElement as defineIpTooltip } from '@norconsult-digital-public/isypixel/web-components/components/ip-tooltip.js';
10
11
  @ProxyCmp({
11
12
  defineCustomElementFn: defineIpButton,
12
- inputs: ['alignIcon', 'disabled', 'loading', 'size', 'type', 'variant']
13
+ inputs: ['alignIcon', 'ariaLabel', 'disabled', 'loading', 'size', 'type', 'variant']
13
14
  })
14
15
  @Component({
15
16
  selector: 'ip-button',
16
17
  changeDetection: ChangeDetectionStrategy.OnPush,
17
18
  template: '<ng-content></ng-content>',
18
19
  // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
19
- inputs: ['alignIcon', 'disabled', 'loading', 'size', 'type', 'variant'],
20
+ inputs: ['alignIcon', 'ariaLabel', 'disabled', 'loading', 'size', 'type', 'variant'],
20
21
  })
21
22
  export class IpButton {
22
23
  protected el: HTMLIpButtonElement;
23
24
  /**
25
+ * Accessible name forwarded to the inner <button>. Useful for icon-only usage, and when provided it overrides the accessible name derived from any slotted label text. @default null
26
+ */
27
+ set ariaLabel(_: Components.IpButton['ariaLabel']) {};
28
+ /**
24
29
  * Visual variant of the button @default 'primary'
25
30
  */
26
31
  set variant(_: Components.IpButton['variant']) {};
@@ -54,3 +59,66 @@ export class IpButton {
54
59
  export declare interface IpButton extends Components.IpButton {}
55
60
 
56
61
 
62
+ @ProxyCmp({
63
+ defineCustomElementFn: defineIpTooltip,
64
+ inputs: ['arrow', 'delay', 'disabled', 'maxWidth', 'position', 'size', 'visible']
65
+ })
66
+ @Component({
67
+ selector: 'ip-tooltip',
68
+ changeDetection: ChangeDetectionStrategy.OnPush,
69
+ template: '<ng-content></ng-content>',
70
+ // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
71
+ inputs: ['arrow', 'delay', 'disabled', 'maxWidth', 'position', 'size', 'visible'],
72
+ outputs: ['show', 'hide'],
73
+ })
74
+ export class IpTooltip {
75
+ protected el: HTMLIpTooltipElement;
76
+ /**
77
+ * Placement of the tooltip bubble relative to the trigger element. @default 'top'
78
+ */
79
+ set position(_: Components.IpTooltip['position']) {};
80
+ /**
81
+ * Visual size of the tooltip bubble. @default 'medium'
82
+ */
83
+ set size(_: Components.IpTooltip['size']) {};
84
+ /**
85
+ * Delay in milliseconds before the tooltip appears on hover. @default 300
86
+ */
87
+ set delay(_: Components.IpTooltip['delay']) {};
88
+ /**
89
+ * Forces the tooltip visible regardless of hover or focus state. @default false
90
+ */
91
+ set visible(_: Components.IpTooltip['visible']) {};
92
+ /**
93
+ * Prevents the tooltip from showing on hover or focus. @default false
94
+ */
95
+ set disabled(_: Components.IpTooltip['disabled']) {};
96
+ /**
97
+ * Renders a directional arrow pointing toward the trigger element. @default true
98
+ */
99
+ set arrow(_: Components.IpTooltip['arrow']) {};
100
+ /**
101
+ * Maximum width of the tooltip bubble. Use absolute or viewport units — percentage values are not supported as they resolve relative to the trigger element. E.g. "300px", "20rem", "50vw". @default '300px'
102
+ */
103
+ set maxWidth(_: Components.IpTooltip['maxWidth']) {};
104
+ @Output() show = new EventEmitter<CustomEvent<void>>();
105
+ @Output() hide = new EventEmitter<CustomEvent<void>>();
106
+ constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
107
+ c.detach();
108
+ this.el = r.nativeElement;
109
+ }
110
+ }
111
+
112
+
113
+ export declare interface IpTooltip extends Components.IpTooltip {
114
+ /**
115
+ * Emitted when the tooltip transitions from hidden to visible.
116
+ */
117
+ show: EventEmitter<CustomEvent<void>>;
118
+ /**
119
+ * Emitted when the tooltip transitions from visible to hidden.
120
+ */
121
+ hide: EventEmitter<CustomEvent<void>>;
122
+ }
123
+
124
+
@@ -1,2 +1,2 @@
1
1
  import * as d from './components';
2
- export declare const DIRECTIVES: (typeof d.IpButton)[];
2
+ export declare const DIRECTIVES: (typeof d.IpButton | typeof d.IpTooltip)[];
@@ -1,4 +1,5 @@
1
1
  import * as d from './components';
2
2
  export const DIRECTIVES = [
3
- d.IpButton
3
+ d.IpButton,
4
+ d.IpTooltip
4
5
  ];
@@ -2,5 +2,6 @@
2
2
  import * as d from './components';
3
3
 
4
4
  export const DIRECTIVES = [
5
- d.IpButton
5
+ d.IpButton,
6
+ d.IpTooltip
6
7
  ];
@@ -2,7 +2,14 @@
2
2
  * This file was automatically generated by the Stencil React Output Target.
3
3
  * Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
4
4
  */
5
+ import { type IpTooltipCustomEvent } from "@norconsult-digital-public/isypixel";
5
6
  import { IpButton as IpButtonElement } from "@norconsult-digital-public/isypixel/web-components/components/ip-button.js";
6
- import type { StencilReactComponent } from '@stencil/react-output-target/runtime';
7
+ import { IpTooltip as IpTooltipElement } from "@norconsult-digital-public/isypixel/web-components/components/ip-tooltip.js";
8
+ import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime';
7
9
  export type IpButtonEvents = NonNullable<unknown>;
8
10
  export declare const IpButton: StencilReactComponent<IpButtonElement, IpButtonEvents>;
11
+ export type IpTooltipEvents = {
12
+ onShow: EventName<IpTooltipCustomEvent<void>>;
13
+ onHide: EventName<IpTooltipCustomEvent<void>>;
14
+ };
15
+ export declare const IpTooltip: StencilReactComponent<IpTooltipElement, IpTooltipEvents>;
@@ -1,10 +1,6 @@
1
1
  'use client';
2
- /**
3
- * This file was automatically generated by the Stencil React Output Target.
4
- * Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
5
- */
6
- /* eslint-disable */
7
2
  import { IpButton as IpButtonElement, defineCustomElement as defineIpButton } from "@norconsult-digital-public/isypixel/web-components/components/ip-button.js";
3
+ import { IpTooltip as IpTooltipElement, defineCustomElement as defineIpTooltip } from "@norconsult-digital-public/isypixel/web-components/components/ip-tooltip.js";
8
4
  import { createComponent } from '@stencil/react-output-target/runtime';
9
5
  import React from 'react';
10
6
  export const IpButton = /*@__PURE__*/ createComponent({
@@ -15,3 +11,14 @@ export const IpButton = /*@__PURE__*/ createComponent({
15
11
  events: {},
16
12
  defineCustomElement: defineIpButton
17
13
  });
14
+ export const IpTooltip = /*@__PURE__*/ createComponent({
15
+ tagName: 'ip-tooltip',
16
+ elementClass: IpTooltipElement,
17
+ // @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
18
+ react: React,
19
+ events: {
20
+ onShow: 'show',
21
+ onHide: 'hide'
22
+ },
23
+ defineCustomElement: defineIpTooltip
24
+ });
@@ -7,8 +7,10 @@
7
7
 
8
8
  /* eslint-disable */
9
9
 
10
+ import { type IpTooltipCustomEvent } from "@norconsult-digital-public/isypixel";
10
11
  import { IpButton as IpButtonElement, defineCustomElement as defineIpButton } from "@norconsult-digital-public/isypixel/web-components/components/ip-button.js";
11
- import type { StencilReactComponent } from '@stencil/react-output-target/runtime';
12
+ import { IpTooltip as IpTooltipElement, defineCustomElement as defineIpTooltip } from "@norconsult-digital-public/isypixel/web-components/components/ip-tooltip.js";
13
+ import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime';
12
14
  import { createComponent } from '@stencil/react-output-target/runtime';
13
15
  import React from 'react';
14
16
 
@@ -22,3 +24,20 @@ export const IpButton: StencilReactComponent<IpButtonElement, IpButtonEvents> =
22
24
  events: {} as IpButtonEvents,
23
25
  defineCustomElement: defineIpButton
24
26
  });
27
+
28
+ export type IpTooltipEvents = {
29
+ onShow: EventName<IpTooltipCustomEvent<void>>,
30
+ onHide: EventName<IpTooltipCustomEvent<void>>
31
+ };
32
+
33
+ export const IpTooltip: StencilReactComponent<IpTooltipElement, IpTooltipEvents> = /*@__PURE__*/ createComponent<IpTooltipElement, IpTooltipEvents>({
34
+ tagName: 'ip-tooltip',
35
+ elementClass: IpTooltipElement,
36
+ // @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
37
+ react: React,
38
+ events: {
39
+ onShow: 'show',
40
+ onHide: 'hide'
41
+ } as IpTooltipEvents,
42
+ defineCustomElement: defineIpTooltip
43
+ });
@@ -5,6 +5,7 @@ import type { Components } from '@norconsult-digital-public/isypixel/web-compone
5
5
  declare namespace svelteHTML {
6
6
  interface IntrinsicElements {
7
7
  'ip-button': Partial<Components.IpButton> & { [key: string]: unknown };
8
+ 'ip-tooltip': Partial<Components.IpTooltip> & { [key: string]: unknown };
8
9
  }
9
10
  }
10
11
 
@@ -12,6 +13,7 @@ declare namespace svelteHTML {
12
13
  declare module 'svelte/elements' {
13
14
  interface SvelteHTMLElements {
14
15
  'ip-button': Partial<Components.IpButton> & { [key: string]: unknown };
16
+ 'ip-tooltip': Partial<Components.IpTooltip> & { [key: string]: unknown };
15
17
  }
16
18
  }
17
19
 
@@ -1,3 +1,4 @@
1
1
  import { type StencilVueComponent } from '@stencil/vue-output-target/runtime';
2
2
  import type { JSX } from '@norconsult-digital-public/isypixel/web-components/components';
3
3
  export declare const IpButton: StencilVueComponent<JSX.IpButton>;
4
+ export declare const IpTooltip: StencilVueComponent<JSX.IpTooltip>;
@@ -3,7 +3,9 @@
3
3
  /* auto-generated vue proxies */
4
4
  import { defineContainer } from '@stencil/vue-output-target/runtime';
5
5
  import { defineCustomElement as defineIpButton } from '@norconsult-digital-public/isypixel/web-components/components/ip-button.js';
6
+ import { defineCustomElement as defineIpTooltip } from '@norconsult-digital-public/isypixel/web-components/components/ip-tooltip.js';
6
7
  export const IpButton = /*@__PURE__*/ defineContainer('ip-button', defineIpButton, [
8
+ 'ariaLabel',
7
9
  'variant',
8
10
  'loading',
9
11
  'disabled',
@@ -11,3 +13,17 @@ export const IpButton = /*@__PURE__*/ defineContainer('ip-button', defineIpButto
11
13
  'size',
12
14
  'alignIcon'
13
15
  ]);
16
+ export const IpTooltip = /*@__PURE__*/ defineContainer('ip-tooltip', defineIpTooltip, [
17
+ 'position',
18
+ 'size',
19
+ 'delay',
20
+ 'visible',
21
+ 'disabled',
22
+ 'arrow',
23
+ 'maxWidth',
24
+ 'show',
25
+ 'hide'
26
+ ], [
27
+ 'show',
28
+ 'hide'
29
+ ]);
@@ -6,10 +6,12 @@ import { defineContainer, type StencilVueComponent } from '@stencil/vue-output-t
6
6
  import type { JSX } from '@norconsult-digital-public/isypixel/web-components/components';
7
7
 
8
8
  import { defineCustomElement as defineIpButton } from '@norconsult-digital-public/isypixel/web-components/components/ip-button.js';
9
+ import { defineCustomElement as defineIpTooltip } from '@norconsult-digital-public/isypixel/web-components/components/ip-tooltip.js';
9
10
 
10
11
 
11
12
 
12
13
  export const IpButton: StencilVueComponent<JSX.IpButton> = /*@__PURE__*/ defineContainer<JSX.IpButton>('ip-button', defineIpButton, [
14
+ 'ariaLabel',
13
15
  'variant',
14
16
  'loading',
15
17
  'disabled',
@@ -19,3 +21,19 @@ export const IpButton: StencilVueComponent<JSX.IpButton> = /*@__PURE__*/ defineC
19
21
  ]);
20
22
 
21
23
 
24
+ export const IpTooltip: StencilVueComponent<JSX.IpTooltip> = /*@__PURE__*/ defineContainer<JSX.IpTooltip>('ip-tooltip', defineIpTooltip, [
25
+ 'position',
26
+ 'size',
27
+ 'delay',
28
+ 'visible',
29
+ 'disabled',
30
+ 'arrow',
31
+ 'maxWidth',
32
+ 'show',
33
+ 'hide'
34
+ ], [
35
+ 'show',
36
+ 'hide'
37
+ ]);
38
+
39
+
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@norconsult-digital-public/isypixel",
3
3
  "private": false,
4
- "version": "2.0.1",
4
+ "version": "2.0.2-canary.2",
5
5
  "license": "SEE LICENSE.md",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -85,6 +85,7 @@
85
85
  "lint": "eslint && prettier --check .",
86
86
  "lint:fix": "eslint --fix && prettier --write .",
87
87
  "test": "vitest run",
88
+ "test:e2e": "playwright test",
88
89
  "figma:resolver": "npx tsx ./src/scripts/figma-resolved-values-fixer.ts",
89
90
  "figma:converter": "npx tsx ./src/scripts/figma-export-converter.ts",
90
91
  "dev:components": "stencil build --dev --watch",
@@ -94,7 +95,8 @@
94
95
  "release:prepare": "tsx ./src/scripts/prepare-release.ts",
95
96
  "publish:dev": "npm run build:all && tsx ./src/scripts/compute-next-dev.ts --apply && npm publish --tag dev --no-git-checks",
96
97
  "update": "npx npm-check",
97
- "update:fix": "npx npm-check -u"
98
+ "update:fix": "npx npm-check -u",
99
+ "playground": "tsx ./src/scripts/update-playground.ts"
98
100
  },
99
101
  "dependencies": {
100
102
  "@stencil/react-output-target": "^1.4.2",
@@ -117,9 +119,11 @@
117
119
  "@angular/compiler": "^21.2.5",
118
120
  "@angular/compiler-cli": "^21.2.5",
119
121
  "@angular/core": "^21.2.5",
122
+ "@axe-core/playwright": "^4.11.1",
120
123
  "@changesets/cli": "^2.30.0",
121
124
  "@eslint/js": "^10.0.1",
122
125
  "@figma/rest-api-spec": "^0.36.0",
126
+ "@playwright/test": "^1.58.2",
123
127
  "@stencil/angular-output-target": "^1.3.0",
124
128
  "@stencil/core": "^4.43.3",
125
129
  "@stencil/sass": "^3.2.3",
@@ -127,6 +131,7 @@
127
131
  "@types/react": "^19.2.14",
128
132
  "@types/semver": "^7.7.1",
129
133
  "@vitest/browser": "^4.1.0",
134
+ "axe-core": "^4.11.1",
130
135
  "eslint": "^10.1.0",
131
136
  "eslint-config-prettier": "^10.1.8",
132
137
  "happy-dom": "^20.8.4",
@@ -134,6 +139,7 @@
134
139
  "rxjs": "^7.8.2",
135
140
  "sass": "^1.98.0",
136
141
  "semver": "^7.7.4",
142
+ "serve": "^14.2.6",
137
143
  "tsd": "^0.33.0",
138
144
  "tsx": "^4.21.0",
139
145
  "typescript": "^5.9.3",