@rcarls/rc-tooltip 0.0.0-stage → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,67 @@
1
+ # Changelog
2
+
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 182fcfd: Add `rc-tooltip`, a WAI-ARIA Tooltip wrapper with Popover API enhancement and a positioned fallback.
8
+
9
+ ### Patch Changes
10
+
11
+ - 1179f24: Drop the `@oddbird/css-anchor-positioning` polyfill. Browsers without full
12
+ native anchor positioning now use `AnchorController`'s script positioning,
13
+ which applies the same placement and flip rules and re-positions when the page
14
+ scrolls or the viewport, anchor, or floating element resizes. Those browsers no
15
+ longer download the 41 kB polyfill the first time a popup opens.
16
+ - 5c006de: Ship component CSS minified. Package builds now run the CSS in Lit `css` styles
17
+ and light-DOM structural styles through Lightning CSS, removing comments and
18
+ whitespace while keeping source maps that resolve to each template. Rendered
19
+ styles are unchanged.
20
+
21
+ `@rcarls/rc-common` adds `cssText`, an identity tag that marks a plain CSS
22
+ string for minification. `rc-chip`, `rc-disclosure`, and `rc-accordion` now
23
+ depend on `@rcarls/rc-common` for it.
24
+
25
+ - f1ca82d: Add an anchored, non-modal popover package with a Material rich-tooltip recipe. Share native Popover API visibility and fallback behavior across existing popup components.
26
+ - 622a4f8: Theme popovers and tooltips through the shared token layers. `rc-popover` now
27
+ reads the shared `--rc-popup-*` surface tokens before its own fallbacks, like
28
+ menus and listboxes, and `rc-tooltip` takes its default corner from
29
+ `--rc-radius-sm`. The Material theme sets its popover and tooltip tokens on the
30
+ theme root, so surfaces inside other shadow roots inherit them, and the
31
+ Substrate theme adds popover and tooltip styles.
32
+ - Updated dependencies [e3dfa59]
33
+ - Updated dependencies [50d5610]
34
+ - Updated dependencies [9ee769c]
35
+ - Updated dependencies [1179f24]
36
+ - Updated dependencies [595fe37]
37
+ - Updated dependencies [38cd00c]
38
+ - Updated dependencies [5c006de]
39
+ - Updated dependencies [a6553ff]
40
+ - Updated dependencies [2205478]
41
+ - Updated dependencies [4341311]
42
+ - Updated dependencies [899bb5e]
43
+ - Updated dependencies [25fcfe0]
44
+ - Updated dependencies [51f6403]
45
+ - Updated dependencies [9caca6b]
46
+ - Updated dependencies [b764a3c]
47
+ - Updated dependencies [54d9ead]
48
+ - Updated dependencies [b9175e9]
49
+ - Updated dependencies [c8b762b]
50
+ - Updated dependencies [55e1e7f]
51
+ - Updated dependencies [f1ca82d]
52
+ - Updated dependencies [b87f27b]
53
+ - Updated dependencies [32ebead]
54
+ - Updated dependencies [bfefedd]
55
+ - Updated dependencies [c130173]
56
+ - Updated dependencies [11680b6]
57
+ - Updated dependencies [223d36c]
58
+ - Updated dependencies [7b91a44]
59
+ - Updated dependencies [aa04ead]
60
+ - Updated dependencies [ac65b5b]
61
+ - Updated dependencies [afcfef8]
62
+ - Updated dependencies [11ef1ad]
63
+ - @rcarls/rc-common@0.7.0
64
+
65
+ ## 0.6.0
66
+
67
+ - Add `rc-tooltip`, a Popover API tooltip wrapper with an anchored fallback.
package/README.md CHANGED
@@ -1,3 +1,79 @@
1
- # Temporary Holding Version
1
+ # `@rcarls/rc-tooltip`
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Tooltip wrapper for a consumer-owned trigger and descriptive content, following
4
+ the [WAI-ARIA Tooltip pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/).
5
+
6
+ Docs: [https://richardcarls.github.io/rc-webcomponents/components/rc-tooltip](https://richardcarls.github.io/rc-webcomponents/components/rc-tooltip).
7
+
8
+ ## Installation
9
+
10
+ ```sh
11
+ npm install @rcarls/rc-tooltip
12
+ ```
13
+
14
+ ## Import
15
+
16
+ ```js
17
+ import '@rcarls/rc-tooltip/define';
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ Put the trigger in the `trigger` slot and one descriptive element in the
23
+ `content` slot:
24
+
25
+ ```html
26
+ <rc-tooltip placement="block-end">
27
+ <button slot="trigger">Save</button>
28
+ <span slot="content">Saves the current document.</span>
29
+ </rc-tooltip>
30
+ ```
31
+
32
+ The component adds a stable `id` and `role="tooltip"` to the content and
33
+ adds that ID to the trigger's `aria-describedby` list. The content is shown
34
+ when the trigger receives focus or the pointer enters the trigger, stays open
35
+ while the pointer is over the trigger or content, and closes when Escape is
36
+ pressed or both leave. Tooltip content is descriptive only and must not hold
37
+ interactive controls or receive focus.
38
+
39
+ The native Popover API is used when available. Browsers without a working
40
+ Popover API use the same interaction and the `hidden` attribute as a fallback;
41
+ positioning uses the shared `AnchorController` with logical placement and
42
+ viewport clamping.
43
+
44
+ ## API
45
+
46
+ | Property | Attribute | Type | Default | Description |
47
+ | ------------------- | ----------- | ----------------- | ----------- | ---------------------------------------------------- |
48
+ | `placement` | `placement` | `AnchorPlacement` | `block-end` | Preferred logical placement relative to the trigger. |
49
+ | _(read-only state)_ | `open` | boolean attribute | absent | Set by the component while the tooltip is visible. |
50
+
51
+ ### Slots
52
+
53
+ | Slot | Description |
54
+ | ----------- | ------------------------------------------------------- |
55
+ | `trigger` | Consumer-owned focusable trigger element. |
56
+ | `content` | One consumer-owned element containing descriptive text. |
57
+ | _(default)_ | Fallback content slot when `content` is omitted. |
58
+
59
+ ### CSS custom properties
60
+
61
+ | Property | Default | Description |
62
+ | ------------------------------ | ---------------------- | ---------------------------- |
63
+ | `--rc-tooltip-max-inline-size` | `20rem` | Maximum tooltip inline size. |
64
+ | `--rc-tooltip-padding-block` | `0.25em` | Block-axis padding. |
65
+ | `--rc-tooltip-padding-inline` | `0.5em` | Inline-axis padding. |
66
+ | `--rc-tooltip-border` | `1px solid CanvasText` | Tooltip border. |
67
+ | `--rc-tooltip-radius` | `var(--rc-radius-sm)` | Tooltip corner radius. |
68
+ | `--rc-tooltip-background` | `CanvasText` | Tooltip background. |
69
+ | `--rc-tooltip-color` | `Canvas` | Tooltip text color. |
70
+ | `--rc-tooltip-shadow` | `none` | Tooltip shadow. |
71
+ | `--rc-tooltip-font` | `inherit` | Tooltip font. |
72
+ | `--rc-tooltip-line-height` | `normal` | Tooltip line height. |
73
+ | `--rc-tooltip-z-index` | `1` | Fallback stacking order. |
74
+
75
+ ### CSS parts
76
+
77
+ | Part | Description |
78
+ | ------ | ---------------------------------------- |
79
+ | `root` | Shadow-DOM wrapper containing the slots. |
@@ -0,0 +1,457 @@
1
+ {
2
+ "schemaVersion": "1.0.0",
3
+ "readme": "",
4
+ "modules": [
5
+ {
6
+ "kind": "javascript-module",
7
+ "path": "src/define.ts",
8
+ "declarations": [],
9
+ "exports": [
10
+ {
11
+ "kind": "custom-element-definition",
12
+ "name": "rc-tooltip",
13
+ "declaration": {
14
+ "name": "RCTooltip",
15
+ "module": "/src/index.js"
16
+ }
17
+ },
18
+ {
19
+ "kind": "js",
20
+ "name": "*",
21
+ "declaration": {
22
+ "name": "*",
23
+ "module": "src/index.js"
24
+ }
25
+ }
26
+ ]
27
+ },
28
+ {
29
+ "kind": "javascript-module",
30
+ "path": "src/index.ts",
31
+ "declarations": [],
32
+ "exports": [
33
+ {
34
+ "kind": "js",
35
+ "name": "RCTooltip",
36
+ "declaration": {
37
+ "name": "default",
38
+ "module": "./rc-tooltip.js"
39
+ }
40
+ },
41
+ {
42
+ "kind": "js",
43
+ "name": "RCTooltipPlacement",
44
+ "declaration": {
45
+ "name": "RCTooltipPlacement",
46
+ "module": "./rc-tooltip.js"
47
+ }
48
+ }
49
+ ]
50
+ },
51
+ {
52
+ "kind": "javascript-module",
53
+ "path": "src/rc-tooltip.ts",
54
+ "declarations": [
55
+ {
56
+ "kind": "class",
57
+ "description": "Tooltip wrapper for a consumer-owned trigger and descriptive content,\nfollowing the [WAI-ARIA Tooltip pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/).\nThe trigger remains in light DOM and receives `aria-describedby`; the\ncontent remains in light DOM so the ID relationship works across browsers.\n\nThe native Popover API is used when the supplied content supports it. Older\nbrowsers use the same focus, pointer, Escape, and anchor positioning logic\nwith an explicit visibility fallback. Tooltip content is descriptive and\nmust not contain interactive controls or receive focus.",
58
+ "name": "RCTooltip",
59
+ "cssProperties": [
60
+ {
61
+ "description": "Maximum inline size of the tooltip content.",
62
+ "name": "--rc-tooltip-max-inline-size",
63
+ "default": "20rem"
64
+ },
65
+ {
66
+ "description": "Tooltip block-axis padding.",
67
+ "name": "--rc-tooltip-padding-block",
68
+ "default": "0.25em"
69
+ },
70
+ {
71
+ "description": "Tooltip inline-axis padding.",
72
+ "name": "--rc-tooltip-padding-inline",
73
+ "default": "0.5em"
74
+ },
75
+ {
76
+ "description": "Tooltip border.",
77
+ "name": "--rc-tooltip-border",
78
+ "default": "1px solid CanvasText"
79
+ },
80
+ {
81
+ "description": "Tooltip corner radius.",
82
+ "name": "--rc-tooltip-radius",
83
+ "default": "var(--rc-radius-sm)"
84
+ },
85
+ {
86
+ "description": "Tooltip background.",
87
+ "name": "--rc-tooltip-background",
88
+ "default": "CanvasText"
89
+ },
90
+ {
91
+ "description": "Tooltip text color.",
92
+ "name": "--rc-tooltip-color",
93
+ "default": "Canvas"
94
+ },
95
+ {
96
+ "description": "Tooltip shadow.",
97
+ "name": "--rc-tooltip-shadow",
98
+ "default": "none"
99
+ },
100
+ {
101
+ "description": "Tooltip font.",
102
+ "name": "--rc-tooltip-font",
103
+ "default": "inherit"
104
+ },
105
+ {
106
+ "description": "Tooltip line height.",
107
+ "name": "--rc-tooltip-line-height",
108
+ "default": "normal"
109
+ },
110
+ {
111
+ "description": "Tooltip stacking order in the fallback mode.",
112
+ "name": "--rc-tooltip-z-index",
113
+ "default": "1"
114
+ }
115
+ ],
116
+ "cssParts": [
117
+ {
118
+ "description": "The shadow-DOM wrapper containing the two slots.",
119
+ "name": "root"
120
+ }
121
+ ],
122
+ "slots": [
123
+ {
124
+ "description": "The consumer-owned element that receives focus and hover behavior.",
125
+ "name": "trigger"
126
+ },
127
+ {
128
+ "description": "The single consumer-owned element containing the tooltip text.",
129
+ "name": "content"
130
+ },
131
+ {
132
+ "description": "A fallback content slot when `content` is omitted.",
133
+ "name": "default"
134
+ }
135
+ ],
136
+ "members": [
137
+ {
138
+ "kind": "field",
139
+ "name": "_styledRoots",
140
+ "privacy": "private",
141
+ "static": true,
142
+ "readonly": true,
143
+ "default": "new WeakSet<Document | ShadowRoot>()"
144
+ },
145
+ {
146
+ "kind": "field",
147
+ "name": "placement",
148
+ "type": {
149
+ "text": "RCTooltipPlacement"
150
+ },
151
+ "default": "'block-end'",
152
+ "description": "Preferred logical placement relative to the trigger.",
153
+ "attribute": "placement"
154
+ },
155
+ {
156
+ "kind": "field",
157
+ "name": "_$triggerSlot",
158
+ "type": {
159
+ "text": "HTMLSlotElement"
160
+ },
161
+ "privacy": "private"
162
+ },
163
+ {
164
+ "kind": "field",
165
+ "name": "_$contentSlot",
166
+ "type": {
167
+ "text": "HTMLSlotElement"
168
+ },
169
+ "privacy": "private"
170
+ },
171
+ {
172
+ "kind": "field",
173
+ "name": "_$defaultSlot",
174
+ "type": {
175
+ "text": "HTMLSlotElement"
176
+ },
177
+ "privacy": "private"
178
+ },
179
+ {
180
+ "kind": "field",
181
+ "name": "_$trigger",
182
+ "type": {
183
+ "text": "HTMLElement | null"
184
+ },
185
+ "privacy": "private",
186
+ "default": "null"
187
+ },
188
+ {
189
+ "kind": "field",
190
+ "name": "_$content",
191
+ "type": {
192
+ "text": "HTMLElement | null"
193
+ },
194
+ "privacy": "private",
195
+ "default": "null"
196
+ },
197
+ {
198
+ "kind": "field",
199
+ "name": "_contentState",
200
+ "type": {
201
+ "text": "ContentState | null"
202
+ },
203
+ "privacy": "private",
204
+ "default": "null"
205
+ },
206
+ {
207
+ "kind": "field",
208
+ "name": "_triggerDescribedBy",
209
+ "type": {
210
+ "text": "string | null"
211
+ },
212
+ "privacy": "private",
213
+ "default": "null"
214
+ },
215
+ {
216
+ "kind": "field",
217
+ "name": "_visible",
218
+ "type": {
219
+ "text": "boolean"
220
+ },
221
+ "privacy": "private",
222
+ "default": "false"
223
+ },
224
+ {
225
+ "kind": "field",
226
+ "name": "_focusWithin",
227
+ "type": {
228
+ "text": "boolean"
229
+ },
230
+ "privacy": "private",
231
+ "default": "false"
232
+ },
233
+ {
234
+ "kind": "field",
235
+ "name": "_pointerWithin",
236
+ "type": {
237
+ "text": "boolean"
238
+ },
239
+ "privacy": "private",
240
+ "default": "false"
241
+ },
242
+ {
243
+ "kind": "field",
244
+ "name": "_dismissedByEscape",
245
+ "type": {
246
+ "text": "boolean"
247
+ },
248
+ "privacy": "private",
249
+ "default": "false"
250
+ },
251
+ {
252
+ "kind": "field",
253
+ "name": "_slotSyncQueued",
254
+ "type": {
255
+ "text": "boolean"
256
+ },
257
+ "privacy": "private",
258
+ "default": "false"
259
+ },
260
+ {
261
+ "kind": "field",
262
+ "name": "_anchor",
263
+ "privacy": "private",
264
+ "readonly": true,
265
+ "default": "new AnchorController(this, { anchor: () => this._$trigger, floating: () => this._$content, placement: this.placement, offset: 4, disabled: () => !this._visible, })"
266
+ },
267
+ {
268
+ "kind": "field",
269
+ "name": "_popover",
270
+ "privacy": "private",
271
+ "readonly": true,
272
+ "default": "new PopoverController(this, { element: () => this._$content })"
273
+ },
274
+ {
275
+ "kind": "method",
276
+ "name": "_ensureBaseStyles",
277
+ "privacy": "private",
278
+ "static": true,
279
+ "return": {
280
+ "type": {
281
+ "text": "void"
282
+ }
283
+ },
284
+ "parameters": [
285
+ {
286
+ "name": "root",
287
+ "type": {
288
+ "text": "Document | ShadowRoot"
289
+ }
290
+ }
291
+ ]
292
+ },
293
+ {
294
+ "kind": "field",
295
+ "name": "_onSlotChange",
296
+ "privacy": "private"
297
+ },
298
+ {
299
+ "kind": "method",
300
+ "name": "_queueSlotSync",
301
+ "privacy": "private",
302
+ "return": {
303
+ "type": {
304
+ "text": "void"
305
+ }
306
+ }
307
+ },
308
+ {
309
+ "kind": "method",
310
+ "name": "_syncSlots",
311
+ "privacy": "private",
312
+ "return": {
313
+ "type": {
314
+ "text": "void"
315
+ }
316
+ }
317
+ },
318
+ {
319
+ "kind": "method",
320
+ "name": "_applyContentSemantics",
321
+ "privacy": "private",
322
+ "return": {
323
+ "type": {
324
+ "text": "void"
325
+ }
326
+ }
327
+ },
328
+ {
329
+ "kind": "method",
330
+ "name": "_syncTriggerDescription",
331
+ "privacy": "private",
332
+ "return": {
333
+ "type": {
334
+ "text": "void"
335
+ }
336
+ }
337
+ },
338
+ {
339
+ "kind": "method",
340
+ "name": "_restoreTrigger",
341
+ "privacy": "private",
342
+ "return": {
343
+ "type": {
344
+ "text": "void"
345
+ }
346
+ }
347
+ },
348
+ {
349
+ "kind": "method",
350
+ "name": "_restoreContent",
351
+ "privacy": "private",
352
+ "return": {
353
+ "type": {
354
+ "text": "void"
355
+ }
356
+ }
357
+ },
358
+ {
359
+ "kind": "field",
360
+ "name": "_onFocusIn",
361
+ "privacy": "private"
362
+ },
363
+ {
364
+ "kind": "field",
365
+ "name": "_onFocusOut",
366
+ "privacy": "private"
367
+ },
368
+ {
369
+ "kind": "field",
370
+ "name": "_onPointerOver",
371
+ "privacy": "private"
372
+ },
373
+ {
374
+ "kind": "field",
375
+ "name": "_onPointerOut",
376
+ "privacy": "private"
377
+ },
378
+ {
379
+ "kind": "field",
380
+ "name": "_onKeyDown",
381
+ "privacy": "private"
382
+ },
383
+ {
384
+ "kind": "method",
385
+ "name": "_syncVisibility",
386
+ "privacy": "private",
387
+ "return": {
388
+ "type": {
389
+ "text": "void"
390
+ }
391
+ }
392
+ },
393
+ {
394
+ "kind": "method",
395
+ "name": "_openTooltip",
396
+ "privacy": "private",
397
+ "return": {
398
+ "type": {
399
+ "text": "void"
400
+ }
401
+ }
402
+ },
403
+ {
404
+ "kind": "method",
405
+ "name": "_closeTooltip",
406
+ "privacy": "private",
407
+ "return": {
408
+ "type": {
409
+ "text": "void"
410
+ }
411
+ }
412
+ }
413
+ ],
414
+ "attributes": [
415
+ {
416
+ "description": "Preferred logical placement relative to the trigger.",
417
+ "name": "placement",
418
+ "type": {
419
+ "text": "RCTooltipPlacement"
420
+ },
421
+ "default": "'block-end'",
422
+ "fieldName": "placement"
423
+ },
424
+ {
425
+ "description": "Reflects the tooltip's visible state; set by the component.",
426
+ "name": "open"
427
+ }
428
+ ],
429
+ "superclass": {
430
+ "name": "LitElement",
431
+ "package": "lit"
432
+ },
433
+ "tagName": "rc-tooltip",
434
+ "customElement": true
435
+ }
436
+ ],
437
+ "exports": [
438
+ {
439
+ "kind": "js",
440
+ "name": "RCTooltip",
441
+ "declaration": {
442
+ "name": "RCTooltip",
443
+ "module": "src/rc-tooltip.ts"
444
+ }
445
+ },
446
+ {
447
+ "kind": "js",
448
+ "name": "default",
449
+ "declaration": {
450
+ "name": "RCTooltip",
451
+ "module": "src/rc-tooltip.ts"
452
+ }
453
+ }
454
+ ]
455
+ }
456
+ ]
457
+ }
@@ -0,0 +1,137 @@
1
+ import { css as d, LitElement as _, html as p } from "lit";
2
+ import { property as u, query as a } from "lit/decorators.js";
3
+ import { AnchorController as g, PopoverController as f, cssText as b } from "@rcarls/rc-common";
4
+ const y = d`:host{color-scheme:inherit;display:inline-block}[part=root]{display:inline-block}@media (forced-colors:active){slot[name=content]::slotted(*){color:canvas;background:canvastext;border-color:canvastext}}`;
5
+ var m = Object.defineProperty, r = (c, t, e, i) => {
6
+ for (var s = void 0, l = c.length - 1, h; l >= 0; l--)
7
+ (h = c[l]) && (s = h(t, e, s) || s);
8
+ return s && m(t, e, s), s;
9
+ };
10
+ let v = 0;
11
+ const S = b`@layer rc-base{rc-tooltip>[slot=content],rc-tooltip>:not([slot]){box-sizing:border-box;max-inline-size:var(--rc-tooltip-max-inline-size,20rem);padding-block:var(--rc-tooltip-padding-block,.25em);padding-inline:var(--rc-tooltip-padding-inline,.5em);border:var(--rc-tooltip-border,1px solid CanvasText);border-radius:var(--rc-tooltip-radius,var(--rc-radius-sm,.125em));background:var(--rc-tooltip-background,CanvasText);color:var(--rc-tooltip-color,Canvas);box-shadow:var(--rc-tooltip-shadow,none);font:var(--rc-tooltip-font,inherit);line-height:var(--rc-tooltip-line-height,normal);overflow-wrap:anywhere;pointer-events:auto;z-index:var(--rc-tooltip-z-index,1);display:block;position:fixed}rc-tooltip>[slot=content][hidden],rc-tooltip>:not([slot])[hidden]{display:none!important}}`;
12
+ var n;
13
+ const o = (n = class extends _ {
14
+ constructor() {
15
+ super(...arguments), this.placement = "block-end", this._$trigger = null, this._$content = null, this._contentState = null, this._triggerDescribedBy = null, this._visible = !1, this._focusWithin = !1, this._pointerWithin = !1, this._dismissedByEscape = !1, this._slotSyncQueued = !1, this._anchor = new g(this, {
16
+ anchor: () => this._$trigger,
17
+ floating: () => this._$content,
18
+ placement: this.placement,
19
+ offset: 4,
20
+ disabled: () => !this._visible
21
+ }), this._popover = new f(this, { element: () => this._$content }), this._onSlotChange = () => {
22
+ this._queueSlotSync();
23
+ }, this._onFocusIn = (t) => {
24
+ this._$trigger && t.composedPath().includes(this._$trigger) && (this._focusWithin = !0, this._syncVisibility());
25
+ }, this._onFocusOut = (t) => {
26
+ const e = t.relatedTarget;
27
+ e instanceof Node && this.contains(e) || this._$trigger && t.composedPath().includes(this._$trigger) && (this._focusWithin = !1, this._dismissedByEscape = !1, this._syncVisibility());
28
+ }, this._onPointerOver = (t) => {
29
+ if (t.pointerType === "touch")
30
+ return;
31
+ const e = t.composedPath();
32
+ (this._$trigger && e.includes(this._$trigger) || this._$content && e.includes(this._$content)) && (this._pointerWithin = !0, this._dismissedByEscape = !1, this._syncVisibility());
33
+ }, this._onPointerOut = (t) => {
34
+ if (t.pointerType === "touch")
35
+ return;
36
+ const e = t.relatedTarget;
37
+ if (e instanceof Node && this.contains(e))
38
+ return;
39
+ const i = t.composedPath();
40
+ (this._$trigger && i.includes(this._$trigger) || this._$content && i.includes(this._$content)) && (this._pointerWithin = !1, this._syncVisibility());
41
+ }, this._onKeyDown = (t) => {
42
+ t.key !== "Escape" || !this._visible || (t.stopPropagation(), this._dismissedByEscape = !0, this._focusWithin = !1, this._pointerWithin = !1, this._closeTooltip());
43
+ };
44
+ }
45
+ connectedCallback() {
46
+ super.connectedCallback(), n._ensureBaseStyles(this.getRootNode()), this.addEventListener("focusin", this._onFocusIn), this.addEventListener("focusout", this._onFocusOut), this.addEventListener("pointerover", this._onPointerOver), this.addEventListener("pointerout", this._onPointerOut), this.addEventListener("keydown", this._onKeyDown), this.hasUpdated && this._queueSlotSync();
47
+ }
48
+ disconnectedCallback() {
49
+ this.removeEventListener("focusin", this._onFocusIn), this.removeEventListener("focusout", this._onFocusOut), this.removeEventListener("pointerover", this._onPointerOver), this.removeEventListener("pointerout", this._onPointerOut), this.removeEventListener("keydown", this._onKeyDown), this._focusWithin = !1, this._pointerWithin = !1, this._dismissedByEscape = !1, this._closeTooltip(), this._restoreTrigger(), this._restoreContent(), this._$trigger = null, this._$content = null, super.disconnectedCallback();
50
+ }
51
+ firstUpdated() {
52
+ this._queueSlotSync();
53
+ }
54
+ updated(t) {
55
+ t.has("placement") && this._anchor.setOptions({ placement: this.placement });
56
+ }
57
+ render() {
58
+ return p`
59
+ <div id="root" part="root">
60
+ <slot name="trigger" @slotchange=${this._onSlotChange}></slot>
61
+ <slot name="content" @slotchange=${this._onSlotChange}></slot>
62
+ <slot @slotchange=${this._onSlotChange}></slot>
63
+ </div>
64
+ `;
65
+ }
66
+ static _ensureBaseStyles(t) {
67
+ if (n._styledRoots.has(t))
68
+ return;
69
+ n._styledRoots.add(t);
70
+ const e = (t instanceof Document ? t : t.ownerDocument).createElement("style");
71
+ e.setAttribute("data-rc-light-dom-base", "rc-tooltip"), e.textContent = S, t instanceof Document ? t.head.append(e) : t.append(e);
72
+ }
73
+ _queueSlotSync() {
74
+ this._slotSyncQueued || (this._slotSyncQueued = !0, queueMicrotask(() => {
75
+ this._slotSyncQueued = !1, this.isConnected && this._syncSlots();
76
+ }));
77
+ }
78
+ _syncSlots() {
79
+ const t = this._$triggerSlot?.assignedElements({ flatten: !0 }).find((i) => i instanceof HTMLElement) ?? null, e = this._$contentSlot?.assignedElements({ flatten: !0 }).find((i) => i instanceof HTMLElement) ?? this._$defaultSlot?.assignedElements({ flatten: !0 }).find((i) => i instanceof HTMLElement) ?? null;
80
+ e !== this._$content && (this._closeTooltip(), this._restoreTrigger(), this._restoreContent(), this._$content = e, this._contentState = null, this._applyContentSemantics()), t !== this._$trigger && (this._restoreTrigger(), this._$trigger = t, this._triggerDescribedBy = null), this._applyContentSemantics(), this._syncTriggerDescription(), this._syncVisibility(), this._visible && this._anchor.update();
81
+ }
82
+ _applyContentSemantics() {
83
+ const t = this._$content;
84
+ t && (this._contentState || (this._contentState = {
85
+ id: t.getAttribute("id"),
86
+ role: t.getAttribute("role"),
87
+ ariaHidden: t.getAttribute("aria-hidden"),
88
+ popover: t.getAttribute("popover"),
89
+ hidden: t.hidden
90
+ }), t.id || (t.id = `rc-tooltip-${++v}`), t.setAttribute("role", "tooltip"), t.setAttribute("popover", "manual"), t.toggleAttribute("hidden", !this._visible), t.setAttribute("aria-hidden", String(!this._visible)));
91
+ }
92
+ _syncTriggerDescription() {
93
+ const t = this._$trigger, e = this._$content;
94
+ if (!t || !e?.id)
95
+ return;
96
+ const i = t.getAttribute("aria-describedby");
97
+ this._triggerDescribedBy === null && (this._triggerDescribedBy = i);
98
+ const s = new Set((i ?? "").split(/\s+/).filter(Boolean));
99
+ s.has(e.id) || s.add(e.id), t.setAttribute("aria-describedby", Array.from(s).join(" "));
100
+ }
101
+ _restoreTrigger() {
102
+ !this._$trigger || this._triggerDescribedBy === null || (this._triggerDescribedBy === "" ? this._$trigger.removeAttribute("aria-describedby") : this._$trigger.setAttribute("aria-describedby", this._triggerDescribedBy), this._triggerDescribedBy = null);
103
+ }
104
+ _restoreContent() {
105
+ const t = this._$content, e = this._contentState;
106
+ !t || !e || (this._popover.sync(!1), e.id === null ? t.removeAttribute("id") : t.setAttribute("id", e.id), e.role === null ? t.removeAttribute("role") : t.setAttribute("role", e.role), e.ariaHidden === null ? t.removeAttribute("aria-hidden") : t.setAttribute("aria-hidden", e.ariaHidden), e.popover === null ? t.removeAttribute("popover") : t.setAttribute("popover", e.popover), t.hidden = e.hidden, this._contentState = null);
107
+ }
108
+ _syncVisibility() {
109
+ const t = !this._dismissedByEscape && (this._focusWithin || this._pointerWithin) && !!this._$content;
110
+ t !== this._visible && (t ? this._openTooltip() : this._closeTooltip());
111
+ }
112
+ _openTooltip() {
113
+ const t = this._$content;
114
+ t && (this._visible = !0, this.toggleAttribute("open", !0), this._applyContentSemantics(), t.hidden = !1, this._popover.sync(!0), this._anchor.update());
115
+ }
116
+ _closeTooltip() {
117
+ const t = this._$content;
118
+ this._visible = !1, this.toggleAttribute("open", !1), t && (this._popover.sync(!1), t.hidden = !0, t.setAttribute("aria-hidden", "true")), this._anchor.update();
119
+ }
120
+ }, n.styles = y, n._styledRoots = /* @__PURE__ */ new WeakSet(), n);
121
+ r([
122
+ u({ type: String })
123
+ ], o.prototype, "placement");
124
+ r([
125
+ a("slot[name='trigger']")
126
+ ], o.prototype, "_$triggerSlot");
127
+ r([
128
+ a("slot[name='content']")
129
+ ], o.prototype, "_$contentSlot");
130
+ r([
131
+ a("slot:not([name])")
132
+ ], o.prototype, "_$defaultSlot");
133
+ let C = o;
134
+ export {
135
+ C as R
136
+ };
137
+ //# sourceMappingURL=rc-tooltip-_7Ftj7QB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-tooltip-_7Ftj7QB.js","sources":["../src/rc-tooltip.styles.ts","../src/rc-tooltip.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const tooltipStyles = css`\n :host {\n display: inline-block;\n color-scheme: inherit;\n }\n\n [part='root'] {\n display: inline-block;\n }\n\n @media (forced-colors: active) {\n slot[name='content']::slotted(*) {\n border-color: CanvasText;\n background: CanvasText;\n color: Canvas;\n }\n }\n`;\n\nexport default tooltipStyles;\n","import { LitElement, html } from 'lit';\nimport { property, query } from 'lit/decorators.js';\n\nimport {\n AnchorController,\n type AnchorPlacement,\n cssText,\n PopoverController,\n} from '@rcarls/rc-common';\n\nimport tooltipStyles from './rc-tooltip.styles.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-tooltip': RCTooltip;\n }\n}\n\nexport type RCTooltipPlacement = AnchorPlacement;\n\ntype ContentState = {\n id: string | null;\n role: string | null;\n ariaHidden: string | null;\n popover: string | null;\n hidden: boolean;\n};\n\nlet tooltipId = 0;\n\nconst LIGHT_DOM_CSS = cssText`\n@layer rc-base {\n rc-tooltip > [slot='content'],\n rc-tooltip > :not([slot]) {\n position: fixed;\n display: block;\n box-sizing: border-box;\n max-inline-size: var(--rc-tooltip-max-inline-size, 20rem);\n padding-block: var(--rc-tooltip-padding-block, 0.25em);\n padding-inline: var(--rc-tooltip-padding-inline, 0.5em);\n border: var(--rc-tooltip-border, 1px solid CanvasText);\n border-radius: var(--rc-tooltip-radius, var(--rc-radius-sm, 0.125em));\n background: var(--rc-tooltip-background, CanvasText);\n color: var(--rc-tooltip-color, Canvas);\n box-shadow: var(--rc-tooltip-shadow, none);\n font: var(--rc-tooltip-font, inherit);\n line-height: var(--rc-tooltip-line-height, normal);\n overflow-wrap: anywhere;\n pointer-events: auto;\n z-index: var(--rc-tooltip-z-index, 1);\n }\n\n rc-tooltip > [slot='content'][hidden],\n rc-tooltip > :not([slot])[hidden] {\n display: none !important;\n }\n}\n`;\n\n/**\n * Tooltip wrapper for a consumer-owned trigger and descriptive content,\n * following the [WAI-ARIA Tooltip pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/).\n * The trigger remains in light DOM and receives `aria-describedby`; the\n * content remains in light DOM so the ID relationship works across browsers.\n *\n * The native Popover API is used when the supplied content supports it. Older\n * browsers use the same focus, pointer, Escape, and anchor positioning logic\n * with an explicit visibility fallback. Tooltip content is descriptive and\n * must not contain interactive controls or receive focus.\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-tooltip rc-tooltip docs}\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/ WAI-ARIA Tooltip pattern}\n *\n * @slot trigger - The consumer-owned element that receives focus and hover behavior.\n * @slot content - The single consumer-owned element containing the tooltip text.\n * @slot default - A fallback content slot when `content` is omitted.\n *\n * @csspart root - The shadow-DOM wrapper containing the two slots.\n *\n * @cssprop [--rc-tooltip-max-inline-size=20rem] - Maximum inline size of the tooltip content.\n * @cssprop [--rc-tooltip-padding-block=0.25em] - Tooltip block-axis padding.\n * @cssprop [--rc-tooltip-padding-inline=0.5em] - Tooltip inline-axis padding.\n * @cssprop [--rc-tooltip-border=1px solid CanvasText] - Tooltip border.\n * @cssprop [--rc-tooltip-radius=var(--rc-radius-sm)] - Tooltip corner radius.\n * @cssprop [--rc-tooltip-background=CanvasText] - Tooltip background.\n * @cssprop [--rc-tooltip-color=Canvas] - Tooltip text color.\n * @cssprop [--rc-tooltip-shadow=none] - Tooltip shadow.\n * @cssprop [--rc-tooltip-font=inherit] - Tooltip font.\n * @cssprop [--rc-tooltip-line-height=normal] - Tooltip line height.\n * @cssprop [--rc-tooltip-z-index=1] - Tooltip stacking order in the fallback mode.\n *\n * @attr placement - Preferred logical placement relative to the trigger.\n * @attr [open] - Reflects the tooltip's visible state; set by the component.\n */\nexport class RCTooltip extends LitElement {\n static override styles = tooltipStyles;\n\n private static readonly _styledRoots = new WeakSet<Document | ShadowRoot>();\n\n /** Preferred logical placement relative to the trigger. */\n @property({ type: String })\n placement: RCTooltipPlacement = 'block-end';\n\n @query(\"slot[name='trigger']\")\n private _$triggerSlot!: HTMLSlotElement;\n\n @query(\"slot[name='content']\")\n private _$contentSlot!: HTMLSlotElement;\n\n @query('slot:not([name])')\n private _$defaultSlot!: HTMLSlotElement;\n\n private _$trigger: HTMLElement | null = null;\n private _$content: HTMLElement | null = null;\n private _contentState: ContentState | null = null;\n private _triggerDescribedBy: string | null = null;\n private _visible = false;\n private _focusWithin = false;\n private _pointerWithin = false;\n private _dismissedByEscape = false;\n private _slotSyncQueued = false;\n\n private readonly _anchor = new AnchorController(this, {\n anchor: () => this._$trigger,\n floating: () => this._$content,\n placement: this.placement,\n offset: 4,\n disabled: () => !this._visible,\n });\n\n private readonly _popover = new PopoverController(this, { element: () => this._$content });\n\n override connectedCallback(): void {\n super.connectedCallback();\n RCTooltip._ensureBaseStyles(this.getRootNode() as Document | ShadowRoot);\n this.addEventListener('focusin', this._onFocusIn);\n this.addEventListener('focusout', this._onFocusOut);\n this.addEventListener('pointerover', this._onPointerOver);\n this.addEventListener('pointerout', this._onPointerOut);\n this.addEventListener('keydown', this._onKeyDown);\n\n if (this.hasUpdated) {\n this._queueSlotSync();\n }\n }\n\n override disconnectedCallback(): void {\n this.removeEventListener('focusin', this._onFocusIn);\n this.removeEventListener('focusout', this._onFocusOut);\n this.removeEventListener('pointerover', this._onPointerOver);\n this.removeEventListener('pointerout', this._onPointerOut);\n this.removeEventListener('keydown', this._onKeyDown);\n this._focusWithin = false;\n this._pointerWithin = false;\n this._dismissedByEscape = false;\n this._closeTooltip();\n this._restoreTrigger();\n this._restoreContent();\n this._$trigger = null;\n this._$content = null;\n super.disconnectedCallback();\n }\n\n protected override firstUpdated(): void {\n this._queueSlotSync();\n\n if (import.meta.env.DEV && !this.querySelector(':scope > [slot=\"trigger\"]')) {\n console.warn(\n '[rc-tooltip] No direct child [slot=\"trigger\"] found. Place the trigger element in the trigger slot.',\n this,\n );\n }\n\n if (\n import.meta.env.DEV &&\n !this.querySelector(':scope > [slot=\"content\"]') &&\n !this.querySelector(':scope > :not([slot])')\n ) {\n console.warn(\n '[rc-tooltip] No direct tooltip content found. Place one element in the content slot.',\n this,\n );\n }\n }\n\n protected override updated(changed: Map<PropertyKey, unknown>): void {\n if (changed.has('placement')) {\n this._anchor.setOptions({ placement: this.placement });\n }\n }\n\n protected override render() {\n return html`\n <div id=\"root\" part=\"root\">\n <slot name=\"trigger\" @slotchange=${this._onSlotChange}></slot>\n <slot name=\"content\" @slotchange=${this._onSlotChange}></slot>\n <slot @slotchange=${this._onSlotChange}></slot>\n </div>\n `;\n }\n\n private static _ensureBaseStyles(root: Document | ShadowRoot): void {\n if (RCTooltip._styledRoots.has(root)) {\n return;\n }\n\n RCTooltip._styledRoots.add(root);\n\n const style = (root instanceof Document ? root : root.ownerDocument).createElement('style');\n\n style.setAttribute('data-rc-light-dom-base', 'rc-tooltip');\n style.textContent = LIGHT_DOM_CSS;\n\n if (root instanceof Document) {\n root.head.append(style);\n } else {\n root.append(style);\n }\n }\n\n private _onSlotChange = (): void => {\n this._queueSlotSync();\n };\n\n private _queueSlotSync(): void {\n if (this._slotSyncQueued) {\n return;\n }\n\n this._slotSyncQueued = true;\n\n queueMicrotask(() => {\n this._slotSyncQueued = false;\n\n if (this.isConnected) {\n this._syncSlots();\n }\n });\n }\n\n private _syncSlots(): void {\n const trigger =\n this._$triggerSlot\n ?.assignedElements({ flatten: true })\n .find((element): element is HTMLElement => element instanceof HTMLElement) ?? null;\n const content =\n this._$contentSlot\n ?.assignedElements({ flatten: true })\n .find((element): element is HTMLElement => element instanceof HTMLElement) ??\n this._$defaultSlot\n ?.assignedElements({ flatten: true })\n .find((element): element is HTMLElement => element instanceof HTMLElement) ??\n null;\n\n if (content !== this._$content) {\n this._closeTooltip();\n this._restoreTrigger();\n this._restoreContent();\n this._$content = content;\n this._contentState = null;\n this._applyContentSemantics();\n }\n\n if (trigger !== this._$trigger) {\n this._restoreTrigger();\n this._$trigger = trigger;\n this._triggerDescribedBy = null;\n }\n\n this._applyContentSemantics();\n this._syncTriggerDescription();\n this._syncVisibility();\n\n if (this._visible) {\n this._anchor.update();\n }\n }\n\n private _applyContentSemantics(): void {\n const content = this._$content;\n\n if (!content) {\n return;\n }\n\n if (!this._contentState) {\n this._contentState = {\n id: content.getAttribute('id'),\n role: content.getAttribute('role'),\n ariaHidden: content.getAttribute('aria-hidden'),\n popover: content.getAttribute('popover'),\n hidden: content.hidden,\n };\n }\n\n if (!content.id) {\n content.id = `rc-tooltip-${++tooltipId}`;\n }\n\n content.setAttribute('role', 'tooltip');\n content.setAttribute('popover', 'manual');\n content.toggleAttribute('hidden', !this._visible);\n content.setAttribute('aria-hidden', String(!this._visible));\n }\n\n private _syncTriggerDescription(): void {\n const trigger = this._$trigger;\n const content = this._$content;\n\n if (!trigger || !content?.id) {\n return;\n }\n\n const current = trigger.getAttribute('aria-describedby');\n\n if (this._triggerDescribedBy === null) {\n this._triggerDescribedBy = current;\n }\n\n const tokens = new Set((current ?? '').split(/\\s+/).filter(Boolean));\n\n if (!tokens.has(content.id)) {\n tokens.add(content.id);\n }\n\n trigger.setAttribute('aria-describedby', Array.from(tokens).join(' '));\n }\n\n private _restoreTrigger(): void {\n if (!this._$trigger || this._triggerDescribedBy === null) {\n return;\n }\n\n if (this._triggerDescribedBy === '') {\n this._$trigger.removeAttribute('aria-describedby');\n } else {\n this._$trigger.setAttribute('aria-describedby', this._triggerDescribedBy);\n }\n\n this._triggerDescribedBy = null;\n }\n\n private _restoreContent(): void {\n const content = this._$content;\n const state = this._contentState;\n\n if (!content || !state) {\n return;\n }\n\n this._popover.sync(false);\n\n if (state.id === null) {\n content.removeAttribute('id');\n } else {\n content.setAttribute('id', state.id);\n }\n\n if (state.role === null) {\n content.removeAttribute('role');\n } else {\n content.setAttribute('role', state.role);\n }\n\n if (state.ariaHidden === null) {\n content.removeAttribute('aria-hidden');\n } else {\n content.setAttribute('aria-hidden', state.ariaHidden);\n }\n\n if (state.popover === null) {\n content.removeAttribute('popover');\n } else {\n content.setAttribute('popover', state.popover);\n }\n\n content.hidden = state.hidden;\n this._contentState = null;\n }\n\n private _onFocusIn = (event: FocusEvent): void => {\n if (this._$trigger && event.composedPath().includes(this._$trigger)) {\n this._focusWithin = true;\n this._syncVisibility();\n }\n };\n\n private _onFocusOut = (event: FocusEvent): void => {\n const relatedTarget = event.relatedTarget;\n\n if (relatedTarget instanceof Node && this.contains(relatedTarget)) {\n return;\n }\n\n if (this._$trigger && event.composedPath().includes(this._$trigger)) {\n this._focusWithin = false;\n this._dismissedByEscape = false;\n this._syncVisibility();\n }\n };\n\n private _onPointerOver = (event: PointerEvent): void => {\n if (event.pointerType === 'touch') {\n return;\n }\n\n const path = event.composedPath();\n\n if (\n (this._$trigger && path.includes(this._$trigger)) ||\n (this._$content && path.includes(this._$content))\n ) {\n this._pointerWithin = true;\n this._dismissedByEscape = false;\n this._syncVisibility();\n }\n };\n\n private _onPointerOut = (event: PointerEvent): void => {\n if (event.pointerType === 'touch') {\n return;\n }\n\n const relatedTarget = event.relatedTarget;\n\n if (relatedTarget instanceof Node && this.contains(relatedTarget)) {\n return;\n }\n\n const path = event.composedPath();\n\n if (\n (this._$trigger && path.includes(this._$trigger)) ||\n (this._$content && path.includes(this._$content))\n ) {\n this._pointerWithin = false;\n this._syncVisibility();\n }\n };\n\n private _onKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape' || !this._visible) {\n return;\n }\n\n event.stopPropagation();\n this._dismissedByEscape = true;\n this._focusWithin = false;\n this._pointerWithin = false;\n this._closeTooltip();\n };\n\n private _syncVisibility(): void {\n const shouldOpen =\n !this._dismissedByEscape && (this._focusWithin || this._pointerWithin) && !!this._$content;\n\n if (shouldOpen === this._visible) {\n return;\n }\n\n if (shouldOpen) {\n this._openTooltip();\n } else {\n this._closeTooltip();\n }\n }\n\n private _openTooltip(): void {\n const content = this._$content;\n\n if (!content) {\n return;\n }\n\n this._visible = true;\n this.toggleAttribute('open', true);\n this._applyContentSemantics();\n content.hidden = false;\n\n this._popover.sync(true);\n\n this._anchor.update();\n }\n\n private _closeTooltip(): void {\n const content = this._$content;\n\n this._visible = false;\n this.toggleAttribute('open', false);\n\n if (content) {\n this._popover.sync(false);\n content.hidden = true;\n content.setAttribute('aria-hidden', 'true');\n }\n\n this._anchor.update();\n }\n}\n\nexport default RCTooltip;\n"],"names":["tooltipStyles","css","tooltipId","LIGHT_DOM_CSS","cssText","_RCTooltip","_a","LitElement","AnchorController","PopoverController","event","relatedTarget","path","changed","html","root","style","trigger","element","content","current","tokens","state","shouldOpen","__decorateClass","property","query","RCTooltip"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { R as t } from "./rc-tooltip-_7Ftj7QB.js";
2
+ customElements.get("rc-tooltip") || customElements.define("rc-tooltip", t);
3
+ export {
4
+ t as RCTooltip
5
+ };
6
+ //# sourceMappingURL=rc-tooltip-define.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-tooltip-define.js","sources":["../src/define.ts"],"sourcesContent":["import { RCTooltip } from './index.js';\n\ncustomElements.get('rc-tooltip') || customElements.define('rc-tooltip', RCTooltip);\n\nexport * from './index.js';\n"],"names":["RCTooltip"],"mappings":";AAEA,eAAe,IAAI,YAAY,KAAK,eAAe,OAAO,cAAcA,CAAS;"}
@@ -0,0 +1,5 @@
1
+ import { R as r } from "./rc-tooltip-_7Ftj7QB.js";
2
+ export {
3
+ r as RCTooltip
4
+ };
5
+ //# sourceMappingURL=rc-tooltip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-tooltip.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1 @@
1
+ export * from './index.js';
@@ -0,0 +1,2 @@
1
+ export { default as RCTooltip } from './rc-tooltip.js';
2
+ export type { RCTooltipPlacement } from './rc-tooltip.js';
@@ -0,0 +1,85 @@
1
+ import { LitElement } from 'lit';
2
+ import { AnchorPlacement } from '@rcarls/rc-common';
3
+ declare global {
4
+ interface HTMLElementTagNameMap {
5
+ 'rc-tooltip': RCTooltip;
6
+ }
7
+ }
8
+ export type RCTooltipPlacement = AnchorPlacement;
9
+ /**
10
+ * Tooltip wrapper for a consumer-owned trigger and descriptive content,
11
+ * following the [WAI-ARIA Tooltip pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/).
12
+ * The trigger remains in light DOM and receives `aria-describedby`; the
13
+ * content remains in light DOM so the ID relationship works across browsers.
14
+ *
15
+ * The native Popover API is used when the supplied content supports it. Older
16
+ * browsers use the same focus, pointer, Escape, and anchor positioning logic
17
+ * with an explicit visibility fallback. Tooltip content is descriptive and
18
+ * must not contain interactive controls or receive focus.
19
+ *
20
+ * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-tooltip rc-tooltip docs}
21
+ * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/ WAI-ARIA Tooltip pattern}
22
+ *
23
+ * @slot trigger - The consumer-owned element that receives focus and hover behavior.
24
+ * @slot content - The single consumer-owned element containing the tooltip text.
25
+ * @slot default - A fallback content slot when `content` is omitted.
26
+ *
27
+ * @csspart root - The shadow-DOM wrapper containing the two slots.
28
+ *
29
+ * @cssprop [--rc-tooltip-max-inline-size=20rem] - Maximum inline size of the tooltip content.
30
+ * @cssprop [--rc-tooltip-padding-block=0.25em] - Tooltip block-axis padding.
31
+ * @cssprop [--rc-tooltip-padding-inline=0.5em] - Tooltip inline-axis padding.
32
+ * @cssprop [--rc-tooltip-border=1px solid CanvasText] - Tooltip border.
33
+ * @cssprop [--rc-tooltip-radius=var(--rc-radius-sm)] - Tooltip corner radius.
34
+ * @cssprop [--rc-tooltip-background=CanvasText] - Tooltip background.
35
+ * @cssprop [--rc-tooltip-color=Canvas] - Tooltip text color.
36
+ * @cssprop [--rc-tooltip-shadow=none] - Tooltip shadow.
37
+ * @cssprop [--rc-tooltip-font=inherit] - Tooltip font.
38
+ * @cssprop [--rc-tooltip-line-height=normal] - Tooltip line height.
39
+ * @cssprop [--rc-tooltip-z-index=1] - Tooltip stacking order in the fallback mode.
40
+ *
41
+ * @attr placement - Preferred logical placement relative to the trigger.
42
+ * @attr [open] - Reflects the tooltip's visible state; set by the component.
43
+ */
44
+ export declare class RCTooltip extends LitElement {
45
+ static styles: import('lit').CSSResult;
46
+ private static readonly _styledRoots;
47
+ /** Preferred logical placement relative to the trigger. */
48
+ placement: RCTooltipPlacement;
49
+ private _$triggerSlot;
50
+ private _$contentSlot;
51
+ private _$defaultSlot;
52
+ private _$trigger;
53
+ private _$content;
54
+ private _contentState;
55
+ private _triggerDescribedBy;
56
+ private _visible;
57
+ private _focusWithin;
58
+ private _pointerWithin;
59
+ private _dismissedByEscape;
60
+ private _slotSyncQueued;
61
+ private readonly _anchor;
62
+ private readonly _popover;
63
+ connectedCallback(): void;
64
+ disconnectedCallback(): void;
65
+ protected firstUpdated(): void;
66
+ protected updated(changed: Map<PropertyKey, unknown>): void;
67
+ protected render(): import('lit-html').TemplateResult<1>;
68
+ private static _ensureBaseStyles;
69
+ private _onSlotChange;
70
+ private _queueSlotSync;
71
+ private _syncSlots;
72
+ private _applyContentSemantics;
73
+ private _syncTriggerDescription;
74
+ private _restoreTrigger;
75
+ private _restoreContent;
76
+ private _onFocusIn;
77
+ private _onFocusOut;
78
+ private _onPointerOver;
79
+ private _onPointerOut;
80
+ private _onKeyDown;
81
+ private _syncVisibility;
82
+ private _openTooltip;
83
+ private _closeTooltip;
84
+ }
85
+ export default RCTooltip;
@@ -0,0 +1,2 @@
1
+ export declare const tooltipStyles: import('lit').CSSResult;
2
+ export default tooltipStyles;
package/package.json CHANGED
@@ -1,6 +1,65 @@
1
1
  {
2
2
  "name": "@rcarls/rc-tooltip",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "0.7.0",
7
+ "description": "Tooltip wrapper for a consumer-owned trigger and descriptive content.",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/richardcarls/rc-webcomponents.git",
11
+ "directory": "packages/rc-tooltip"
12
+ },
13
+ "homepage": "https://richardcarls.github.io/rc-webcomponents/components/rc-tooltip",
14
+ "license": "MIT",
15
+ "type": "module",
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "module": "./dist/rc-tooltip.js",
20
+ "exports": {
21
+ ".": {
22
+ "import": {
23
+ "types": "./dist/types/packages/rc-tooltip/src/index.d.ts",
24
+ "default": "./dist/rc-tooltip.js"
25
+ }
26
+ },
27
+ "./define": {
28
+ "import": {
29
+ "types": "./dist/types/packages/rc-tooltip/src/define.d.ts",
30
+ "default": "./dist/rc-tooltip-define.js"
31
+ }
32
+ }
33
+ },
34
+ "types": "./dist/types/packages/rc-tooltip/src/index.d.ts",
35
+ "sideEffects": [
36
+ "./dist/rc-tooltip-define.js"
37
+ ],
38
+ "customElements": "dist/custom-elements.json",
39
+ "scripts": {
40
+ "build": "tsc && vite build && cem analyze",
41
+ "cem:analyze": "cem analyze",
42
+ "preview": "vite preview",
43
+ "test:browser": "vitest --run",
44
+ "test:browser:chrome": "vitest --run --project=chromium",
45
+ "test:browser:firefox": "vitest --run --project=firefox"
46
+ },
47
+ "dependencies": {
48
+ "@rcarls/rc-common": "0.7.0"
49
+ },
50
+ "devDependencies": {
51
+ "@custom-elements-manifest/analyzer": "0.11.0",
52
+ "@vitest/browser-playwright": "4.1.5",
53
+ "lit": "^3.0.0",
54
+ "playwright": "^1.56.0",
55
+ "rollup": "^4.60.2",
56
+ "typescript": "~5.9.3",
57
+ "vite": "^7.1.7",
58
+ "vite-plugin-dts": "^4.5.4",
59
+ "vitest": "^4.0.6",
60
+ "vitest-browser-lit": "^1.0.1"
61
+ },
62
+ "peerDependencies": {
63
+ "lit": "^3.0.0"
64
+ }
6
65
  }