daisyui 2.2.1 → 2.2.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/README.md +10 -1
- data/app/javascript/daisy_ui/controllers/daisy_tooltip_controller.js +67 -2
- data/app/javascript/daisy_ui/controllers/daisy_tooltip_controller.min.js +2 -2
- data/app/javascript/daisy_ui/controllers/daisy_tooltip_controller.min.js.map +3 -3
- data/lib/daisy_ui/class_merge/daisy_groups.rb +18 -3
- data/lib/daisy_ui/updated_at.rb +1 -1
- data/lib/daisy_ui/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ab063470f9b99ad71dc3f9478536d3df9a07373fc6755a3c396b32a7d0a99bc7
|
|
4
|
+
data.tar.gz: a49ac6b55190c2e2c0043d4cec89eaa11445545b74b77c4d91cdcd9eba107f7d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cb6541c2ffed9f0fa4d3d3d59630fd88a18fdf266d414c582c709591e53c8a3095b1260b65997f2133cb3ef9f12edcfb22c47a08758a78e6240e98c908f89871
|
|
7
|
+
data.tar.gz: dff649b560f90152a45011f8534a343d97bb21d40c886275eb6d411933421e8dc190c43e84be192bde43ddc1b50a8b735b0806ccd178fe59dcd25876f7ff17af
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
### Fixed
|
|
4
4
|
|
|
5
|
+
- A `:popover` `Tooltip` opens on a touch screen. The `daisy-tooltip`
|
|
6
|
+
controller toggles it on a touch or pen tap and keeps it open after the
|
|
7
|
+
finger lifts, until a tap outside, a second tap on the trigger, Escape or
|
|
8
|
+
focus moving to another element; before, a tap showed it for one frame and
|
|
9
|
+
hid it again on iOS Safari. `toggle` is also a Stimulus action (`click->daisy-tooltip#toggle`). Hover
|
|
10
|
+
and keyboard behaviour are unchanged, and no window or document listener is
|
|
11
|
+
attached while the tooltip is closed (#76).
|
|
12
|
+
|
|
13
|
+
## [2.2.2] - 2026-10-27
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- A variant member's classes no longer knock each other out. A group now holds
|
|
18
|
+
only the component's own `<component_class>-*` classes; a member's other
|
|
19
|
+
classes Tailwind does not classify (plugin utilities such as
|
|
20
|
+
`motion-opacity-in-0 motion-duration-[400ms]`) are ungrouped, as a flag's
|
|
21
|
+
are, so all of them render. A component without a `component_class` groups
|
|
22
|
+
none of its own classes; globally configured grouped modifiers are unchanged
|
|
23
|
+
(#73).
|
|
24
|
+
|
|
25
|
+
## [2.2.1] - 2026-10-27
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
5
29
|
- The Tailwind sources generator accepts named groups and peers
|
|
6
30
|
(`group/item`, `group-has-[…]/item:block`, `peer-checked/field:block`) and a
|
|
7
31
|
plugin utility's named modifier (`motion-ease-in-out/opacity`) instead of
|
data/README.md
CHANGED
|
@@ -269,6 +269,12 @@ dependency). daisyUI modifiers conflict when the component declares them as
|
|
|
269
269
|
alternatives in one group: `btn-sm btn-lg` keeps `btn-lg`, while
|
|
270
270
|
`dropdown-top dropdown-end` keeps both (placement and alignment are separate
|
|
271
271
|
groups). Ungrouped modifiers (`btn-wide`, `btn-active`) never conflict.
|
|
272
|
+
A group holds only the component's own `<component_class>-*` classes: a
|
|
273
|
+
member's Tailwind utilities resolve by Tailwind's groups, and any other class
|
|
274
|
+
in it (a plugin utility such as `motion-duration-[400ms]`) never conflicts, so
|
|
275
|
+
the classes of one member never knock each other out. To make such classes
|
|
276
|
+
alternatives, set the component's `component_class` and name them
|
|
277
|
+
`<component_class>-*`, or register them with `class_groups` (below).
|
|
272
278
|
Component base classes such as `table` and `collapse` are never dropped.
|
|
273
279
|
|
|
274
280
|
Register custom utilities so the merger knows what they are. Unregistered,
|
|
@@ -382,7 +388,7 @@ Widget(:ghost, :sm) # btn font-medium btn-ghost btn-sm [--fontsize:…] [--btn-b
|
|
|
382
388
|
|
|
383
389
|
| Declaration | |
|
|
384
390
|
|---|---|
|
|
385
|
-
| `variant :group, member: "classes", …` | Alternatives: the grouped `register_modifiers(group: { … })`. Members merge as one ClassMerge group. |
|
|
391
|
+
| `variant :group, member: "classes", …` | Alternatives: the grouped `register_modifiers(group: { … })`. Members' own `<component_class>-*` classes merge as one ClassMerge group. |
|
|
386
392
|
| `flag :name, "classes"` | An on/off modifier: an ungrouped `register_modifiers` entry. `flag :name` alone is a `register_flags` flag, no class, for compounds to match. |
|
|
387
393
|
| `base "classes"` | Classes every instance gets, appended to the inherited base. |
|
|
388
394
|
| `default :group, :member` | The member used when the caller names none of the group. Never rendered beside a member the caller gives. |
|
|
@@ -668,6 +674,9 @@ it as `daisy-tooltip`.
|
|
|
668
674
|
Popover tooltips:
|
|
669
675
|
|
|
670
676
|
- open on pointer hover or keyboard focus and close on leave, blur, or Escape;
|
|
677
|
+
- toggle on a touch or pen tap and then stay open until a tap outside, a second
|
|
678
|
+
tap on the trigger, Escape, or focus moving elsewhere (`toggle` is also a
|
|
679
|
+
Stimulus action, e.g. `click->daisy-tooltip#toggle`);
|
|
671
680
|
- use `role="tooltip"` and merge their id into the first interactive trigger's
|
|
672
681
|
`aria-describedby`;
|
|
673
682
|
- preserve caller-supplied Stimulus controllers;
|
|
@@ -6,6 +6,7 @@ const ARROW_WIDTH = 10
|
|
|
6
6
|
const ARROW_HEIGHT = 4
|
|
7
7
|
const FOCUSABLE_SELECTOR = 'button, a[href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
8
8
|
const OPPOSITE = { top: "bottom", bottom: "top", left: "right", right: "left" }
|
|
9
|
+
const TAP_POINTERS = ["touch", "pen"]
|
|
9
10
|
|
|
10
11
|
// daisy-tooltip — positions a :popover Tooltip in the browser top layer.
|
|
11
12
|
//
|
|
@@ -13,16 +14,29 @@ const OPPOSITE = { top: "bottom", bottom: "top", left: "right", right: "left" }
|
|
|
13
14
|
// hover/focus lifecycle expected of a tooltip, then flips and shifts the real
|
|
14
15
|
// tooltip element only while it is open so it remains inside the visual
|
|
15
16
|
// viewport. No global listeners remain attached while the tooltip is closed.
|
|
17
|
+
//
|
|
18
|
+
// A touch or pen tap toggles the tooltip: it stays open after the finger lifts
|
|
19
|
+
// (pointerleave/focusout no longer close it) until a tap outside, a second tap
|
|
20
|
+
// on the trigger, or Escape. `toggle` is also a Stimulus action, for a host
|
|
21
|
+
// that wires `click->daisy-tooltip#toggle` on its own trigger.
|
|
16
22
|
export default class extends Controller {
|
|
17
23
|
static targets = ["content", "arrow"]
|
|
18
24
|
static values = { placement: { type: String, default: "top" } }
|
|
19
25
|
|
|
20
26
|
connect() {
|
|
27
|
+
// Stimulus reuses this instance when the same element is re-inserted.
|
|
28
|
+
this.openedByTap = false
|
|
29
|
+
this.tapPending = false
|
|
21
30
|
if (!this.hasContentTarget) return
|
|
22
31
|
|
|
23
32
|
this.originalMaxWidth = this.contentTarget.style.maxWidth
|
|
24
|
-
this.onPointerEnter = () => this
|
|
33
|
+
this.onPointerEnter = (event) => this.#handlePointerEnter(event)
|
|
25
34
|
this.onPointerLeave = () => this.#hideUnlessFocused()
|
|
35
|
+
this.onPointerDown = () => {
|
|
36
|
+
this.tapPending = false
|
|
37
|
+
}
|
|
38
|
+
this.onPointerUp = (event) => this.#handlePointerUp(event)
|
|
39
|
+
this.onOutsidePointerDown = (event) => this.#handleOutsidePointerDown(event)
|
|
26
40
|
this.onFocusIn = () => this.show()
|
|
27
41
|
this.onFocusOut = (event) => this.#handleFocusOut(event)
|
|
28
42
|
this.onKeydown = (event) => this.#handleKeydown(event)
|
|
@@ -30,6 +44,8 @@ export default class extends Controller {
|
|
|
30
44
|
|
|
31
45
|
this.element.addEventListener("pointerenter", this.onPointerEnter)
|
|
32
46
|
this.element.addEventListener("pointerleave", this.onPointerLeave)
|
|
47
|
+
this.element.addEventListener("pointerdown", this.onPointerDown)
|
|
48
|
+
this.element.addEventListener("pointerup", this.onPointerUp)
|
|
33
49
|
this.element.addEventListener("focusin", this.onFocusIn)
|
|
34
50
|
this.element.addEventListener("focusout", this.onFocusOut)
|
|
35
51
|
this.#describeTrigger()
|
|
@@ -40,6 +56,8 @@ export default class extends Controller {
|
|
|
40
56
|
disconnect() {
|
|
41
57
|
this.element.removeEventListener("pointerenter", this.onPointerEnter)
|
|
42
58
|
this.element.removeEventListener("pointerleave", this.onPointerLeave)
|
|
59
|
+
this.element.removeEventListener("pointerdown", this.onPointerDown)
|
|
60
|
+
this.element.removeEventListener("pointerup", this.onPointerUp)
|
|
43
61
|
this.element.removeEventListener("focusin", this.onFocusIn)
|
|
44
62
|
this.element.removeEventListener("focusout", this.onFocusOut)
|
|
45
63
|
this.#teardownOpen()
|
|
@@ -57,15 +75,34 @@ export default class extends Controller {
|
|
|
57
75
|
}
|
|
58
76
|
|
|
59
77
|
hide() {
|
|
78
|
+
this.openedByTap = false
|
|
60
79
|
if (this.#isOpen()) this.contentTarget.hidePopover()
|
|
61
80
|
this.contentTarget.style.visibility = "hidden"
|
|
62
81
|
this.#teardownOpen()
|
|
63
82
|
}
|
|
64
83
|
|
|
84
|
+
// Stimulus action. Closes a tooltip a tap opened; otherwise opens it (or
|
|
85
|
+
// keeps a hover/focus-opened one open) until an outside tap or Escape.
|
|
86
|
+
toggle(event) {
|
|
87
|
+
if (event?.type === "click" && this.tapPending) {
|
|
88
|
+
this.tapPending = false
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (this.openedByTap && this.#isOpen()) {
|
|
93
|
+
this.hide()
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
this.show()
|
|
98
|
+
this.openedByTap = this.#isOpen()
|
|
99
|
+
}
|
|
100
|
+
|
|
65
101
|
#setupOpen() {
|
|
66
102
|
window.addEventListener("resize", this.onGeometryChange)
|
|
67
103
|
window.addEventListener("scroll", this.onGeometryChange, true)
|
|
68
104
|
window.addEventListener("keydown", this.onKeydown)
|
|
105
|
+
document.addEventListener("pointerdown", this.onOutsidePointerDown, true)
|
|
69
106
|
window.visualViewport?.addEventListener("resize", this.onGeometryChange)
|
|
70
107
|
window.visualViewport?.addEventListener("scroll", this.onGeometryChange)
|
|
71
108
|
}
|
|
@@ -75,6 +112,7 @@ export default class extends Controller {
|
|
|
75
112
|
window.removeEventListener("resize", this.onGeometryChange)
|
|
76
113
|
window.removeEventListener("scroll", this.onGeometryChange, true)
|
|
77
114
|
window.removeEventListener("keydown", this.onKeydown)
|
|
115
|
+
document.removeEventListener("pointerdown", this.onOutsidePointerDown, true)
|
|
78
116
|
window.visualViewport?.removeEventListener("resize", this.onGeometryChange)
|
|
79
117
|
window.visualViewport?.removeEventListener("scroll", this.onGeometryChange)
|
|
80
118
|
}
|
|
@@ -188,11 +226,38 @@ export default class extends Controller {
|
|
|
188
226
|
}
|
|
189
227
|
}
|
|
190
228
|
|
|
229
|
+
#handlePointerEnter(event) {
|
|
230
|
+
// A finger's pointerenter is the start of the tap that pointerup handles.
|
|
231
|
+
if (event.pointerType === "touch") return
|
|
232
|
+
|
|
233
|
+
this.show()
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
#handlePointerUp(event) {
|
|
237
|
+
if (!TAP_POINTERS.includes(event.pointerType)) return
|
|
238
|
+
|
|
239
|
+
this.toggle()
|
|
240
|
+
this.tapPending = true
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
#handleOutsidePointerDown(event) {
|
|
244
|
+
if (!this.openedByTap) return
|
|
245
|
+
if (this.element.contains(event.target)) return
|
|
246
|
+
|
|
247
|
+
this.hide()
|
|
248
|
+
}
|
|
249
|
+
|
|
191
250
|
#handleFocusOut(event) {
|
|
192
|
-
if (
|
|
251
|
+
if (this.element.contains(event.relatedTarget)) return
|
|
252
|
+
// A tap elsewhere blurs with no relatedTarget; the outside tap closes it.
|
|
253
|
+
// Focus moving to another element (Tab) closes it even when tapped open.
|
|
254
|
+
if (this.openedByTap && !event.relatedTarget) return
|
|
255
|
+
|
|
256
|
+
this.hide()
|
|
193
257
|
}
|
|
194
258
|
|
|
195
259
|
#hideUnlessFocused() {
|
|
260
|
+
if (this.openedByTap) return
|
|
196
261
|
if (!this.element.matches(":focus-within")) this.hide()
|
|
197
262
|
}
|
|
198
263
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{Controller as y}from"@hotwired/stimulus";var a=8,
|
|
1
|
+
import{Controller as y}from"@hotwired/stimulus";var a=8,d=8,f=10,c=4,g='button, a[href], input, select, textarea, [tabindex]:not([tabindex="-1"])',T={top:"bottom",bottom:"top",left:"right",right:"left"},b=["touch","pen"];class E extends y{static targets=["content","arrow"];static values={placement:{type:String,default:"top"}};connect(){if(this.openedByTap=!1,this.tapPending=!1,!this.hasContentTarget)return;if(this.originalMaxWidth=this.contentTarget.style.maxWidth,this.onPointerEnter=(t)=>this.#l(t),this.onPointerLeave=()=>this.#f(),this.onPointerDown=()=>{this.tapPending=!1},this.onPointerUp=(t)=>this.#p(t),this.onOutsidePointerDown=(t)=>this.#u(t),this.onFocusIn=()=>this.show(),this.onFocusOut=(t)=>this.#m(t),this.onKeydown=(t)=>this.#g(t),this.onGeometryChange=()=>this.#i(),this.element.addEventListener("pointerenter",this.onPointerEnter),this.element.addEventListener("pointerleave",this.onPointerLeave),this.element.addEventListener("pointerdown",this.onPointerDown),this.element.addEventListener("pointerup",this.onPointerUp),this.element.addEventListener("focusin",this.onFocusIn),this.element.addEventListener("focusout",this.onFocusOut),this.#w(),this.element.classList.contains("tooltip-open"))this.show()}disconnect(){if(this.element.removeEventListener("pointerenter",this.onPointerEnter),this.element.removeEventListener("pointerleave",this.onPointerLeave),this.element.removeEventListener("pointerdown",this.onPointerDown),this.element.removeEventListener("pointerup",this.onPointerUp),this.element.removeEventListener("focusin",this.onFocusIn),this.element.removeEventListener("focusout",this.onFocusOut),this.#e(),this.#v(),this.hasContentTarget)this.contentTarget.style.maxWidth=this.originalMaxWidth}show(){if(!this.hasContentTarget||this.#t())return;this.contentTarget.style.visibility="hidden",this.contentTarget.showPopover(),this.#r(),this.#i()}hide(){if(this.openedByTap=!1,this.#t())this.contentTarget.hidePopover();this.contentTarget.style.visibility="hidden",this.#e()}toggle(t){if(t?.type==="click"&&this.tapPending){this.tapPending=!1;return}if(this.openedByTap&&this.#t()){this.hide();return}this.show(),this.openedByTap=this.#t()}#r(){window.addEventListener("resize",this.onGeometryChange),window.addEventListener("scroll",this.onGeometryChange,!0),window.addEventListener("keydown",this.onKeydown),document.addEventListener("pointerdown",this.onOutsidePointerDown,!0),window.visualViewport?.addEventListener("resize",this.onGeometryChange),window.visualViewport?.addEventListener("scroll",this.onGeometryChange)}#e(){cancelAnimationFrame(this.frame),window.removeEventListener("resize",this.onGeometryChange),window.removeEventListener("scroll",this.onGeometryChange,!0),window.removeEventListener("keydown",this.onKeydown),document.removeEventListener("pointerdown",this.onOutsidePointerDown,!0),window.visualViewport?.removeEventListener("resize",this.onGeometryChange),window.visualViewport?.removeEventListener("scroll",this.onGeometryChange)}#i(){cancelAnimationFrame(this.frame),this.frame=requestAnimationFrame(()=>this.#h())}#h(){if(!this.#t())return;let t=this.#c(),e=Math.max(0,t.width-a*2);this.contentTarget.style.maxWidth=this.originalMaxWidth;let i=Number.parseFloat(getComputedStyle(this.contentTarget).maxWidth),n=Number.isFinite(i)?Math.min(i,e):e;this.contentTarget.style.maxWidth=`${n}px`;let o=this.element.getBoundingClientRect(),r=this.contentTarget.getBoundingClientRect(),h=this.#n(this.placementValue,o,r),s=T[this.placementValue]||"bottom",l=this.#n(s,o,r),p=this.#s(l,r,t)<this.#s(h,r,t),w=p?s:this.placementValue,v=p?l:h,{x:u,y:m}=this.#a(v,r,t);Object.assign(this.contentTarget.style,{left:`${u}px`,top:`${m}px`,visibility:"visible"}),this.#d(w,o,r,u,m)}#n(t,e,i){let n=e.left+e.width/2,o=e.top+e.height/2;switch(t){case"bottom":return{x:n-i.width/2,y:e.bottom+d};case"left":return{x:e.left-i.width-d,y:o-i.height/2};case"right":return{x:e.right+d,y:o-i.height/2};default:return{x:n-i.width/2,y:e.top-i.height-d}}}#s({x:t,y:e},i,n){let o=n.left+a,r=n.left+n.width-a,h=n.top+a,s=n.top+n.height-a;return Math.max(0,o-t)+Math.max(0,t+i.width-r)+Math.max(0,h-e)+Math.max(0,e+i.height-s)}#a({x:t,y:e},i,n){let o=n.left+a,r=n.left+n.width-a,h=n.top+a,s=n.top+n.height-a;return{x:i.width>r-o?o:Math.min(Math.max(t,o),r-i.width),y:i.height>s-h?h:Math.min(Math.max(e,h),s-i.height)}}#d(t,e,i,n,o){if(!this.hasArrowTarget)return;let r=e.left+e.width/2-n,h=e.top+e.height/2-o,s=this.arrowTarget.style;if(Object.assign(s,{inset:"auto",transform:"none"}),t==="top"||t==="bottom"){if(s.left=`${this.#o(r-f/2,4,i.width-f-4)}px`,t==="top")s.bottom=`${-c}px`;else s.top=`${-c}px`,s.transform="rotate(180deg)";return}if(s.top=`${this.#o(h-c/2,4,i.height-c-4)}px`,t==="left")s.right="-7px",s.transform="rotate(-90deg)";else s.left="-7px",s.transform="rotate(90deg)"}#c(){let t=window.visualViewport;return{left:t?.offsetLeft??0,top:t?.offsetTop??0,width:t?.width??window.innerWidth,height:t?.height??window.innerHeight}}#l(t){if(t.pointerType==="touch")return;this.show()}#p(t){if(!b.includes(t.pointerType))return;this.toggle(),this.tapPending=!0}#u(t){if(!this.openedByTap)return;if(this.element.contains(t.target))return;this.hide()}#m(t){if(this.element.contains(t.relatedTarget))return;if(this.openedByTap&&!t.relatedTarget)return;this.hide()}#f(){if(this.openedByTap)return;if(!this.element.matches(":focus-within"))this.hide()}#g(t){if(t.key!=="Escape")return;this.hide()}#w(){let t=this.element.matches(g)?this.element:this.element.querySelector(g);if(!t||!this.contentTarget.id)return;this.describedTrigger=t,this.previousDescription=t.getAttribute("aria-describedby");let e=this.previousDescription?.split(/\s+/).filter(Boolean)||[];t.setAttribute("aria-describedby",[...new Set([...e,this.contentTarget.id])].join(" "))}#v(){if(!this.describedTrigger)return;if(this.previousDescription===null)this.describedTrigger.removeAttribute("aria-describedby");else this.describedTrigger.setAttribute("aria-describedby",this.previousDescription)}#t(){return this.hasContentTarget&&this.contentTarget.matches(":popover-open")}#o(t,e,i){return Math.min(Math.max(t,e),Math.max(e,i))}}export{E as default};
|
|
2
2
|
|
|
3
|
-
//# debugId=
|
|
3
|
+
//# debugId=241E50245EF6211764756E2164756E21
|
|
4
4
|
//# sourceMappingURL=daisy_tooltip_controller.min.js.map
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["daisy_tooltip_controller.js"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { Controller } from \"@hotwired/stimulus\"\n\nconst VIEWPORT_PADDING = 8\nconst GAP = 8\nconst ARROW_WIDTH = 10\nconst ARROW_HEIGHT = 4\nconst FOCUSABLE_SELECTOR = 'button, a[href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\nconst OPPOSITE = { top: \"bottom\", bottom: \"top\", left: \"right\", right: \"left\" }\n\n// daisy-tooltip — positions a :popover Tooltip in the browser top layer.\n//\n// The Popover API escapes clipping ancestors. This controller supplies the\n// hover/focus lifecycle expected of a tooltip, then flips and shifts the real\n// tooltip element only while it is open so it remains inside the visual\n// viewport. No global listeners remain attached while the tooltip is closed.\nexport default class extends Controller {\n static targets = [\"content\", \"arrow\"]\n static values = { placement: { type: String, default: \"top\" } }\n\n connect() {\n if (!this.hasContentTarget) return\n\n this.originalMaxWidth = this.contentTarget.style.maxWidth\n this.onPointerEnter = () => this.show()\n this.onPointerLeave = () => this.#hideUnlessFocused()\n this.onFocusIn = () => this.show()\n this.onFocusOut = (event) => this.#handleFocusOut(event)\n this.onKeydown = (event) => this.#handleKeydown(event)\n this.onGeometryChange = () => this.#schedulePosition()\n\n this.element.addEventListener(\"pointerenter\", this.onPointerEnter)\n this.element.addEventListener(\"pointerleave\", this.onPointerLeave)\n this.element.addEventListener(\"focusin\", this.onFocusIn)\n this.element.addEventListener(\"focusout\", this.onFocusOut)\n this.#describeTrigger()\n\n if (this.element.classList.contains(\"tooltip-open\")) this.show()\n }\n\n disconnect() {\n this.element.removeEventListener(\"pointerenter\", this.onPointerEnter)\n this.element.removeEventListener(\"pointerleave\", this.onPointerLeave)\n this.element.removeEventListener(\"focusin\", this.onFocusIn)\n this.element.removeEventListener(\"focusout\", this.onFocusOut)\n this.#teardownOpen()\n this.#restoreDescription()\n if (this.hasContentTarget) this.contentTarget.style.maxWidth = this.originalMaxWidth\n }\n\n show() {\n if (!this.hasContentTarget || this.#isOpen()) return\n\n this.contentTarget.style.visibility = \"hidden\"\n this.contentTarget.showPopover()\n this.#setupOpen()\n this.#schedulePosition()\n }\n\n hide() {\n if (this.#isOpen()) this.contentTarget.hidePopover()\n this.contentTarget.style.visibility = \"hidden\"\n this.#teardownOpen()\n }\n\n #setupOpen() {\n window.addEventListener(\"resize\", this.onGeometryChange)\n window.addEventListener(\"scroll\", this.onGeometryChange, true)\n window.addEventListener(\"keydown\", this.onKeydown)\n window.visualViewport?.addEventListener(\"resize\", this.onGeometryChange)\n window.visualViewport?.addEventListener(\"scroll\", this.onGeometryChange)\n }\n\n #teardownOpen() {\n cancelAnimationFrame(this.frame)\n window.removeEventListener(\"resize\", this.onGeometryChange)\n window.removeEventListener(\"scroll\", this.onGeometryChange, true)\n window.removeEventListener(\"keydown\", this.onKeydown)\n window.visualViewport?.removeEventListener(\"resize\", this.onGeometryChange)\n window.visualViewport?.removeEventListener(\"scroll\", this.onGeometryChange)\n }\n\n #schedulePosition() {\n cancelAnimationFrame(this.frame)\n this.frame = requestAnimationFrame(() => this.#position())\n }\n\n #position() {\n if (!this.#isOpen()) return\n\n const viewport = this.#viewport()\n const availableWidth = Math.max(0, viewport.width - VIEWPORT_PADDING * 2)\n this.contentTarget.style.maxWidth = this.originalMaxWidth\n const computedMaxWidth = Number.parseFloat(getComputedStyle(this.contentTarget).maxWidth)\n const maxWidth = Number.isFinite(computedMaxWidth) ? Math.min(computedMaxWidth, availableWidth) : availableWidth\n this.contentTarget.style.maxWidth = `${maxWidth}px`\n\n const trigger = this.element.getBoundingClientRect()\n const tooltip = this.contentTarget.getBoundingClientRect()\n const preferred = this.#coordinates(this.placementValue, trigger, tooltip)\n const oppositePlacement = OPPOSITE[this.placementValue] || \"bottom\"\n const opposite = this.#coordinates(oppositePlacement, trigger, tooltip)\n const useOpposite = this.#overflow(opposite, tooltip, viewport) < this.#overflow(preferred, tooltip, viewport)\n const placement = useOpposite ? oppositePlacement : this.placementValue\n const coordinates = useOpposite ? opposite : preferred\n const { x, y } = this.#shift(coordinates, tooltip, viewport)\n\n Object.assign(this.contentTarget.style, { left: `${x}px`, top: `${y}px`, visibility: \"visible\" })\n this.#positionArrow(placement, trigger, tooltip, x, y)\n }\n\n #coordinates(placement, trigger, tooltip) {\n const centerX = trigger.left + trigger.width / 2\n const centerY = trigger.top + trigger.height / 2\n\n switch (placement) {\n case \"bottom\":\n return { x: centerX - tooltip.width / 2, y: trigger.bottom + GAP }\n case \"left\":\n return { x: trigger.left - tooltip.width - GAP, y: centerY - tooltip.height / 2 }\n case \"right\":\n return { x: trigger.right + GAP, y: centerY - tooltip.height / 2 }\n default:\n return { x: centerX - tooltip.width / 2, y: trigger.top - tooltip.height - GAP }\n }\n }\n\n #overflow({ x, y }, tooltip, viewport) {\n const left = viewport.left + VIEWPORT_PADDING\n const right = viewport.left + viewport.width - VIEWPORT_PADDING\n const top = viewport.top + VIEWPORT_PADDING\n const bottom = viewport.top + viewport.height - VIEWPORT_PADDING\n\n return (\n Math.max(0, left - x) +\n Math.max(0, x + tooltip.width - right) +\n Math.max(0, top - y) +\n Math.max(0, y + tooltip.height - bottom)\n )\n }\n\n #shift({ x, y }, tooltip, viewport) {\n const left = viewport.left + VIEWPORT_PADDING\n const right = viewport.left + viewport.width - VIEWPORT_PADDING\n const top = viewport.top + VIEWPORT_PADDING\n const bottom = viewport.top + viewport.height - VIEWPORT_PADDING\n\n return {\n x: tooltip.width > right - left ? left : Math.min(Math.max(x, left), right - tooltip.width),\n y: tooltip.height > bottom - top ? top : Math.min(Math.max(y, top), bottom - tooltip.height),\n }\n }\n\n #positionArrow(placement, trigger, tooltip, x, y) {\n if (!this.hasArrowTarget) return\n\n const centerX = trigger.left + trigger.width / 2 - x\n const centerY = trigger.top + trigger.height / 2 - y\n const arrow = this.arrowTarget.style\n Object.assign(arrow, { inset: \"auto\", transform: \"none\" })\n\n if (placement === \"top\" || placement === \"bottom\") {\n arrow.left = `${this.#clamp(centerX - ARROW_WIDTH / 2, 4, tooltip.width - ARROW_WIDTH - 4)}px`\n if (placement === \"top\") arrow.bottom = `${-ARROW_HEIGHT}px`\n else {\n arrow.top = `${-ARROW_HEIGHT}px`\n arrow.transform = \"rotate(180deg)\"\n }\n return\n }\n\n arrow.top = `${this.#clamp(centerY - ARROW_HEIGHT / 2, 4, tooltip.height - ARROW_HEIGHT - 4)}px`\n if (placement === \"left\") {\n arrow.right = \"-7px\"\n arrow.transform = \"rotate(-90deg)\"\n } else {\n arrow.left = \"-7px\"\n arrow.transform = \"rotate(90deg)\"\n }\n }\n\n #viewport() {\n const visualViewport = window.visualViewport\n return {\n left: visualViewport?.offsetLeft ?? 0,\n top: visualViewport?.offsetTop ?? 0,\n width: visualViewport?.width ?? window.innerWidth,\n height: visualViewport?.height ?? window.innerHeight,\n }\n }\n\n #handleFocusOut(event) {\n if (!this.element.contains(event.relatedTarget)) this.hide()\n }\n\n #hideUnlessFocused() {\n if (!this.element.matches(\":focus-within\")) this.hide()\n }\n\n #handleKeydown(event) {\n if (event.key !== \"Escape\") return\n\n this.hide()\n }\n\n #describeTrigger() {\n const trigger = this.element.matches(FOCUSABLE_SELECTOR)\n ? this.element\n : this.element.querySelector(FOCUSABLE_SELECTOR)\n if (!trigger || !this.contentTarget.id) return\n\n this.describedTrigger = trigger\n this.previousDescription = trigger.getAttribute(\"aria-describedby\")\n const descriptions = this.previousDescription?.split(/\\s+/).filter(Boolean) || []\n trigger.setAttribute(\"aria-describedby\", [...new Set([...descriptions, this.contentTarget.id])].join(\" \"))\n }\n\n #restoreDescription() {\n if (!this.describedTrigger) return\n\n if (this.previousDescription === null) this.describedTrigger.removeAttribute(\"aria-describedby\")\n else this.describedTrigger.setAttribute(\"aria-describedby\", this.previousDescription)\n }\n\n #isOpen() {\n return this.hasContentTarget && this.contentTarget.matches(\":popover-open\")\n }\n\n #clamp(value, minimum, maximum) {\n return Math.min(Math.max(value, minimum), Math.max(minimum, maximum))\n }\n}\n"
|
|
5
|
+
"import { Controller } from \"@hotwired/stimulus\"\n\nconst VIEWPORT_PADDING = 8\nconst GAP = 8\nconst ARROW_WIDTH = 10\nconst ARROW_HEIGHT = 4\nconst FOCUSABLE_SELECTOR = 'button, a[href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\nconst OPPOSITE = { top: \"bottom\", bottom: \"top\", left: \"right\", right: \"left\" }\nconst TAP_POINTERS = [\"touch\", \"pen\"]\n\n// daisy-tooltip — positions a :popover Tooltip in the browser top layer.\n//\n// The Popover API escapes clipping ancestors. This controller supplies the\n// hover/focus lifecycle expected of a tooltip, then flips and shifts the real\n// tooltip element only while it is open so it remains inside the visual\n// viewport. No global listeners remain attached while the tooltip is closed.\n//\n// A touch or pen tap toggles the tooltip: it stays open after the finger lifts\n// (pointerleave/focusout no longer close it) until a tap outside, a second tap\n// on the trigger, or Escape. `toggle` is also a Stimulus action, for a host\n// that wires `click->daisy-tooltip#toggle` on its own trigger.\nexport default class extends Controller {\n static targets = [\"content\", \"arrow\"]\n static values = { placement: { type: String, default: \"top\" } }\n\n connect() {\n // Stimulus reuses this instance when the same element is re-inserted.\n this.openedByTap = false\n this.tapPending = false\n if (!this.hasContentTarget) return\n\n this.originalMaxWidth = this.contentTarget.style.maxWidth\n this.onPointerEnter = (event) => this.#handlePointerEnter(event)\n this.onPointerLeave = () => this.#hideUnlessFocused()\n this.onPointerDown = () => {\n this.tapPending = false\n }\n this.onPointerUp = (event) => this.#handlePointerUp(event)\n this.onOutsidePointerDown = (event) => this.#handleOutsidePointerDown(event)\n this.onFocusIn = () => this.show()\n this.onFocusOut = (event) => this.#handleFocusOut(event)\n this.onKeydown = (event) => this.#handleKeydown(event)\n this.onGeometryChange = () => this.#schedulePosition()\n\n this.element.addEventListener(\"pointerenter\", this.onPointerEnter)\n this.element.addEventListener(\"pointerleave\", this.onPointerLeave)\n this.element.addEventListener(\"pointerdown\", this.onPointerDown)\n this.element.addEventListener(\"pointerup\", this.onPointerUp)\n this.element.addEventListener(\"focusin\", this.onFocusIn)\n this.element.addEventListener(\"focusout\", this.onFocusOut)\n this.#describeTrigger()\n\n if (this.element.classList.contains(\"tooltip-open\")) this.show()\n }\n\n disconnect() {\n this.element.removeEventListener(\"pointerenter\", this.onPointerEnter)\n this.element.removeEventListener(\"pointerleave\", this.onPointerLeave)\n this.element.removeEventListener(\"pointerdown\", this.onPointerDown)\n this.element.removeEventListener(\"pointerup\", this.onPointerUp)\n this.element.removeEventListener(\"focusin\", this.onFocusIn)\n this.element.removeEventListener(\"focusout\", this.onFocusOut)\n this.#teardownOpen()\n this.#restoreDescription()\n if (this.hasContentTarget) this.contentTarget.style.maxWidth = this.originalMaxWidth\n }\n\n show() {\n if (!this.hasContentTarget || this.#isOpen()) return\n\n this.contentTarget.style.visibility = \"hidden\"\n this.contentTarget.showPopover()\n this.#setupOpen()\n this.#schedulePosition()\n }\n\n hide() {\n this.openedByTap = false\n if (this.#isOpen()) this.contentTarget.hidePopover()\n this.contentTarget.style.visibility = \"hidden\"\n this.#teardownOpen()\n }\n\n // Stimulus action. Closes a tooltip a tap opened; otherwise opens it (or\n // keeps a hover/focus-opened one open) until an outside tap or Escape.\n toggle(event) {\n if (event?.type === \"click\" && this.tapPending) {\n this.tapPending = false\n return\n }\n\n if (this.openedByTap && this.#isOpen()) {\n this.hide()\n return\n }\n\n this.show()\n this.openedByTap = this.#isOpen()\n }\n\n #setupOpen() {\n window.addEventListener(\"resize\", this.onGeometryChange)\n window.addEventListener(\"scroll\", this.onGeometryChange, true)\n window.addEventListener(\"keydown\", this.onKeydown)\n document.addEventListener(\"pointerdown\", this.onOutsidePointerDown, true)\n window.visualViewport?.addEventListener(\"resize\", this.onGeometryChange)\n window.visualViewport?.addEventListener(\"scroll\", this.onGeometryChange)\n }\n\n #teardownOpen() {\n cancelAnimationFrame(this.frame)\n window.removeEventListener(\"resize\", this.onGeometryChange)\n window.removeEventListener(\"scroll\", this.onGeometryChange, true)\n window.removeEventListener(\"keydown\", this.onKeydown)\n document.removeEventListener(\"pointerdown\", this.onOutsidePointerDown, true)\n window.visualViewport?.removeEventListener(\"resize\", this.onGeometryChange)\n window.visualViewport?.removeEventListener(\"scroll\", this.onGeometryChange)\n }\n\n #schedulePosition() {\n cancelAnimationFrame(this.frame)\n this.frame = requestAnimationFrame(() => this.#position())\n }\n\n #position() {\n if (!this.#isOpen()) return\n\n const viewport = this.#viewport()\n const availableWidth = Math.max(0, viewport.width - VIEWPORT_PADDING * 2)\n this.contentTarget.style.maxWidth = this.originalMaxWidth\n const computedMaxWidth = Number.parseFloat(getComputedStyle(this.contentTarget).maxWidth)\n const maxWidth = Number.isFinite(computedMaxWidth) ? Math.min(computedMaxWidth, availableWidth) : availableWidth\n this.contentTarget.style.maxWidth = `${maxWidth}px`\n\n const trigger = this.element.getBoundingClientRect()\n const tooltip = this.contentTarget.getBoundingClientRect()\n const preferred = this.#coordinates(this.placementValue, trigger, tooltip)\n const oppositePlacement = OPPOSITE[this.placementValue] || \"bottom\"\n const opposite = this.#coordinates(oppositePlacement, trigger, tooltip)\n const useOpposite = this.#overflow(opposite, tooltip, viewport) < this.#overflow(preferred, tooltip, viewport)\n const placement = useOpposite ? oppositePlacement : this.placementValue\n const coordinates = useOpposite ? opposite : preferred\n const { x, y } = this.#shift(coordinates, tooltip, viewport)\n\n Object.assign(this.contentTarget.style, { left: `${x}px`, top: `${y}px`, visibility: \"visible\" })\n this.#positionArrow(placement, trigger, tooltip, x, y)\n }\n\n #coordinates(placement, trigger, tooltip) {\n const centerX = trigger.left + trigger.width / 2\n const centerY = trigger.top + trigger.height / 2\n\n switch (placement) {\n case \"bottom\":\n return { x: centerX - tooltip.width / 2, y: trigger.bottom + GAP }\n case \"left\":\n return { x: trigger.left - tooltip.width - GAP, y: centerY - tooltip.height / 2 }\n case \"right\":\n return { x: trigger.right + GAP, y: centerY - tooltip.height / 2 }\n default:\n return { x: centerX - tooltip.width / 2, y: trigger.top - tooltip.height - GAP }\n }\n }\n\n #overflow({ x, y }, tooltip, viewport) {\n const left = viewport.left + VIEWPORT_PADDING\n const right = viewport.left + viewport.width - VIEWPORT_PADDING\n const top = viewport.top + VIEWPORT_PADDING\n const bottom = viewport.top + viewport.height - VIEWPORT_PADDING\n\n return (\n Math.max(0, left - x) +\n Math.max(0, x + tooltip.width - right) +\n Math.max(0, top - y) +\n Math.max(0, y + tooltip.height - bottom)\n )\n }\n\n #shift({ x, y }, tooltip, viewport) {\n const left = viewport.left + VIEWPORT_PADDING\n const right = viewport.left + viewport.width - VIEWPORT_PADDING\n const top = viewport.top + VIEWPORT_PADDING\n const bottom = viewport.top + viewport.height - VIEWPORT_PADDING\n\n return {\n x: tooltip.width > right - left ? left : Math.min(Math.max(x, left), right - tooltip.width),\n y: tooltip.height > bottom - top ? top : Math.min(Math.max(y, top), bottom - tooltip.height),\n }\n }\n\n #positionArrow(placement, trigger, tooltip, x, y) {\n if (!this.hasArrowTarget) return\n\n const centerX = trigger.left + trigger.width / 2 - x\n const centerY = trigger.top + trigger.height / 2 - y\n const arrow = this.arrowTarget.style\n Object.assign(arrow, { inset: \"auto\", transform: \"none\" })\n\n if (placement === \"top\" || placement === \"bottom\") {\n arrow.left = `${this.#clamp(centerX - ARROW_WIDTH / 2, 4, tooltip.width - ARROW_WIDTH - 4)}px`\n if (placement === \"top\") arrow.bottom = `${-ARROW_HEIGHT}px`\n else {\n arrow.top = `${-ARROW_HEIGHT}px`\n arrow.transform = \"rotate(180deg)\"\n }\n return\n }\n\n arrow.top = `${this.#clamp(centerY - ARROW_HEIGHT / 2, 4, tooltip.height - ARROW_HEIGHT - 4)}px`\n if (placement === \"left\") {\n arrow.right = \"-7px\"\n arrow.transform = \"rotate(-90deg)\"\n } else {\n arrow.left = \"-7px\"\n arrow.transform = \"rotate(90deg)\"\n }\n }\n\n #viewport() {\n const visualViewport = window.visualViewport\n return {\n left: visualViewport?.offsetLeft ?? 0,\n top: visualViewport?.offsetTop ?? 0,\n width: visualViewport?.width ?? window.innerWidth,\n height: visualViewport?.height ?? window.innerHeight,\n }\n }\n\n #handlePointerEnter(event) {\n // A finger's pointerenter is the start of the tap that pointerup handles.\n if (event.pointerType === \"touch\") return\n\n this.show()\n }\n\n #handlePointerUp(event) {\n if (!TAP_POINTERS.includes(event.pointerType)) return\n\n this.toggle()\n this.tapPending = true\n }\n\n #handleOutsidePointerDown(event) {\n if (!this.openedByTap) return\n if (this.element.contains(event.target)) return\n\n this.hide()\n }\n\n #handleFocusOut(event) {\n if (this.element.contains(event.relatedTarget)) return\n // A tap elsewhere blurs with no relatedTarget; the outside tap closes it.\n // Focus moving to another element (Tab) closes it even when tapped open.\n if (this.openedByTap && !event.relatedTarget) return\n\n this.hide()\n }\n\n #hideUnlessFocused() {\n if (this.openedByTap) return\n if (!this.element.matches(\":focus-within\")) this.hide()\n }\n\n #handleKeydown(event) {\n if (event.key !== \"Escape\") return\n\n this.hide()\n }\n\n #describeTrigger() {\n const trigger = this.element.matches(FOCUSABLE_SELECTOR)\n ? this.element\n : this.element.querySelector(FOCUSABLE_SELECTOR)\n if (!trigger || !this.contentTarget.id) return\n\n this.describedTrigger = trigger\n this.previousDescription = trigger.getAttribute(\"aria-describedby\")\n const descriptions = this.previousDescription?.split(/\\s+/).filter(Boolean) || []\n trigger.setAttribute(\"aria-describedby\", [...new Set([...descriptions, this.contentTarget.id])].join(\" \"))\n }\n\n #restoreDescription() {\n if (!this.describedTrigger) return\n\n if (this.previousDescription === null) this.describedTrigger.removeAttribute(\"aria-describedby\")\n else this.describedTrigger.setAttribute(\"aria-describedby\", this.previousDescription)\n }\n\n #isOpen() {\n return this.hasContentTarget && this.contentTarget.matches(\":popover-open\")\n }\n\n #clamp(value, minimum, maximum) {\n return Math.min(Math.max(value, minimum), Math.max(minimum, maximum))\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "AAAA,qBAAS,2BAET,IAAM,EAAmB,EACnB,EAAM,EACN,EAAc,GACd,EAAe,EACf,EAAqB,4EACrB,EAAW,CAAE,IAAK,SAAU,OAAQ,MAAO,KAAM,QAAS,MAAO,MAAO,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "241E50245EF6211764756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -8,8 +8,14 @@ module DaisyUI
|
|
|
8
8
|
#
|
|
9
9
|
# gives the group `daisy:group:btn-size` = ["btn-sm", "btn-lg"], so
|
|
10
10
|
# `btn-sm btn-lg` merges to `btn-lg`. Ungrouped modifiers never conflict.
|
|
11
|
+
#
|
|
12
|
+
# A group holds only the component's own `<component_class>-*` classes.
|
|
11
13
|
# Tokens Tailwind already classifies (`bg-primary text-primary-content`)
|
|
12
|
-
# are left to the Tailwind groups, which resolve them per utility.
|
|
14
|
+
# are left to the Tailwind groups, which resolve them per utility. Any
|
|
15
|
+
# other class (a plugin utility such as `motion-duration-[400ms]`) is left
|
|
16
|
+
# ungrouped, as a flag is: a group would make the classes of one member
|
|
17
|
+
# knock each other out. A component without a component_class groups
|
|
18
|
+
# nothing of its own.
|
|
13
19
|
#
|
|
14
20
|
# Every gem component base class (`btn`, `table`) also gets a group of its
|
|
15
21
|
# own and is never dropped, even where Tailwind has a utility of the same
|
|
@@ -33,14 +39,16 @@ module DaisyUI
|
|
|
33
39
|
components.each do |component|
|
|
34
40
|
component.modifier_groups.each do |group, members|
|
|
35
41
|
tokens = members.flat_map { |member| component.modifiers[member].to_s.split }
|
|
36
|
-
add(groups, "daisy:group:#{component.component_class || component.name}-#{group}", tokens, prefix)
|
|
42
|
+
add(groups, "daisy:group:#{component.component_class || component.name}-#{group}", own(tokens, component), prefix)
|
|
37
43
|
end
|
|
38
44
|
end
|
|
39
45
|
|
|
40
46
|
# Configured modifiers join the component's own group of that name.
|
|
47
|
+
# A global one has no component to own its classes: all are grouped.
|
|
41
48
|
configuration.modifiers.groups.each do |(component, group), classes|
|
|
42
49
|
owner = component ? component.component_class || component.name : "global"
|
|
43
|
-
|
|
50
|
+
tokens = classes.flat_map(&:split)
|
|
51
|
+
add(groups, "daisy:group:#{owner}-#{group}", component ? own(tokens, component) : tokens, prefix)
|
|
44
52
|
end
|
|
45
53
|
|
|
46
54
|
groups
|
|
@@ -68,6 +76,13 @@ module DaisyUI
|
|
|
68
76
|
|
|
69
77
|
private
|
|
70
78
|
|
|
79
|
+
# The component's own modifier classes: `btn-sm` for `btn`.
|
|
80
|
+
def own(tokens, component)
|
|
81
|
+
return [] unless (base = component.component_class)
|
|
82
|
+
|
|
83
|
+
tokens.select { |token| token.start_with?("#{base}-") }
|
|
84
|
+
end
|
|
85
|
+
|
|
71
86
|
# Subclasses share their parent's component_class and group names, so
|
|
72
87
|
# their tokens land in the same group id and are unioned.
|
|
73
88
|
def add(groups, id, tokens, prefix)
|
data/lib/daisy_ui/updated_at.rb
CHANGED
data/lib/daisy_ui/version.rb
CHANGED