motile-ui 1.0.1 → 1.0.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.
Files changed (44) hide show
  1. package/dist/components/Accordion/Accordion.css +1 -0
  2. package/dist/components/Accordion/Accordion.js +121 -0
  3. package/dist/components/Badge/Badge.css +1 -0
  4. package/dist/components/Badge/Badge.js +24 -0
  5. package/dist/components/Button/Button.css +1 -0
  6. package/dist/components/Button/Button.js +73 -0
  7. package/dist/components/Checkbox/Checkbox.css +1 -0
  8. package/dist/components/Checkbox/Checkbox.js +69 -0
  9. package/dist/components/Dock/Dock.css +1 -0
  10. package/dist/components/Dock/Dock.js +151 -0
  11. package/dist/components/Drawer/Drawer.css +1 -0
  12. package/dist/components/Drawer/Drawer.js +275 -0
  13. package/dist/components/Input/Input.css +1 -0
  14. package/dist/components/Input/Input.js +122 -0
  15. package/dist/components/Modal/Modal.css +1 -0
  16. package/dist/components/Modal/Modal.js +231 -0
  17. package/dist/components/Popover/Popover.css +1 -0
  18. package/dist/components/Popover/Popover.js +197 -0
  19. package/dist/components/Sheet/Sheet.css +1 -0
  20. package/dist/components/Sheet/Sheet.js +283 -0
  21. package/dist/components/Skeleton/Skeleton.css +1 -0
  22. package/dist/components/Skeleton/Skeleton.js +30 -0
  23. package/dist/components/SpeedDial/SpeedDial.css +1 -0
  24. package/dist/components/SpeedDial/SpeedDial.js +149 -0
  25. package/dist/components/Switch/Switch.css +1 -0
  26. package/dist/components/Switch/Switch.js +31 -0
  27. package/dist/components/Textarea/Textarea.css +1 -0
  28. package/dist/components/Textarea/Textarea.js +111 -0
  29. package/dist/components/Toast/Toast.css +1 -0
  30. package/dist/components/Toast/Toast.js +178 -0
  31. package/dist/components/Toast/useToast.js +30 -0
  32. package/dist/components/Tooltip/Tooltip.css +1 -0
  33. package/dist/components/Tooltip/Tooltip.js +321 -0
  34. package/dist/hooks/useClickOutside.js +24 -0
  35. package/dist/hooks/useEscapeKey.js +18 -0
  36. package/dist/hooks/useHistoryClose.js +42 -0
  37. package/dist/hooks/useScrollLock.js +73 -0
  38. package/dist/index.js +42 -0
  39. package/dist/utils/FloatingArrow.js +55 -0
  40. package/dist/utils/Slot.js +44 -0
  41. package/package.json +88 -6
  42. package/dist/index.css +0 -1
  43. package/dist/motile-ui.es.js +0 -2494
  44. package/dist/motile-ui.umd.js +0 -2
@@ -0,0 +1,31 @@
1
+ import { jsx as e, jsxs as h } from "react/jsx-runtime";
2
+ import { forwardRef as p } from "react";
3
+ import './Switch.css';/* empty css */
4
+ const $ = p(
5
+ ({ variant: t = "smooth", color: o, className: c, disabled: a, style: i, ...n }, l) => {
6
+ const s = "motile-switch", r = [
7
+ `${s}-container`,
8
+ `${s}-container--${t}`,
9
+ a && `${s}-container--disabled`
10
+ ].filter(Boolean).join(" "), m = [s, `${s}--${t}`, c].filter(Boolean).join(" ");
11
+ return /* @__PURE__ */ e("div", { className: r, style: o ? { "--motile-switch-color": o } : void 0, children: /* @__PURE__ */ h("label", { className: `${s}-wrapper`, children: [
12
+ /* @__PURE__ */ e(
13
+ "input",
14
+ {
15
+ ...n,
16
+ ref: l,
17
+ type: "checkbox",
18
+ className: m,
19
+ disabled: a,
20
+ style: i,
21
+ role: "switch"
22
+ }
23
+ ),
24
+ /* @__PURE__ */ e("span", { className: `${s}__track`, children: /* @__PURE__ */ e("span", { className: `${s}__thumb` }) })
25
+ ] }) });
26
+ }
27
+ );
28
+ $.displayName = "Switch";
29
+ export {
30
+ $ as Switch
31
+ };
@@ -0,0 +1 @@
1
+ .motile-textarea-root{display:block;width:100%}.motile-textarea{width:100%;border:2px solid #e5e8eb;border-radius:12px;padding:12px 16px;font-size:16px;font-weight:400;color:#111827;background:#fff;outline:none;transition:none;min-height:120px;line-height:1.6;box-sizing:border-box;font-family:inherit;resize:none}.motile-textarea:hover:not(:disabled):not(:focus):not(.motile-textarea--error){border-color:#c9cdd2}.motile-textarea:focus{border:2px solid var( --motile-textarea-color, var(--motile-ui-textarea, var(--motile-theme, #3182f6)) )}.motile-textarea:disabled{background:#f9fafb;color:#9ca3af;cursor:not-allowed;border-color:#e5e7eb;resize:none}.motile-textarea.motile-textarea--error{border:2px solid #ef4444;background:#fef5f5}.motile-textarea.motile-textarea--error:focus{border:2px solid #ef4444;background:#fef5f5}.motile-textarea--shake{animation:motile-textarea-shake .5s ease-in-out}@keyframes motile-textarea-shake{0%{transform:translate(0)}15%{transform:translate(-10px)}30%{transform:translate(8px)}45%{transform:translate(-6px)}60%{transform:translate(4px)}75%{transform:translate(-2px)}to{transform:translate(0)}}.motile-textarea::placeholder{color:#9ca3af;opacity:1}.motile-textarea-wrapper{position:relative;width:100%}.motile-textarea--with-clear{padding-right:40px}.motile-textarea--with-clear:focus{padding-right:40px}.motile-textarea__clear-button{position:absolute;right:12px;top:12px;display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;background:transparent;border:none;color:#9ca3af;cursor:pointer;border-radius:4px;transition:background-color .2s ease,color .2s ease}.motile-textarea__clear-button:hover{background:#f3f4f6;color:#6b7280}.motile-textarea__clear-icon{width:16px;height:16px}@media (max-width: 768px){.motile-textarea{font-size:16px;padding:12px;min-height:100px}.motile-textarea:focus{border:2px solid var( --motile-textarea-color, var(--motile-ui-textarea, var(--motile-theme, #3182f6)) )}.motile-textarea--with-clear{padding-right:36px}.motile-textarea--with-clear:focus{padding-right:36px}}@supports (-webkit-touch-callout: none){.motile-textarea{-webkit-tap-highlight-color:transparent}}.motile-textarea__helper-text{display:flex;align-items:flex-start;margin-top:4px;min-height:16px;gap:8px}.motile-textarea__helper-text--both{justify-content:space-between}.motile-textarea__helper-text--error-only{justify-content:flex-start}.motile-textarea__helper-text--counter-only{justify-content:flex-end}.motile-textarea__error-message{font-size:12px;color:#ef4444;line-height:16px;flex:1}.motile-textarea__counter{font-size:12px;color:#9ca3af;line-height:16px;white-space:nowrap;flex-shrink:0}.motile-textarea__label{position:absolute;left:16px;top:16px;font-size:16px;color:#9ca3af;pointer-events:none;transition:all .2s ease;background:transparent;padding:0;z-index:1}.motile-textarea--with-label::placeholder{opacity:0}.motile-textarea--with-label:focus::placeholder{opacity:1}.motile-textarea-wrapper:has(.motile-textarea:focus) .motile-textarea__label,.motile-textarea-wrapper:has(.motile-textarea:not(:placeholder-shown)) .motile-textarea__label{top:0;transform:translateY(-50%);font-size:12px;color:var( --motile-textarea-color, var(--motile-ui-textarea, var(--motile-theme, #3182f6)) );background:#fff;padding:0 4px}.motile-textarea-wrapper:has(.motile-textarea:focus) .motile-textarea__label--error,.motile-textarea-wrapper:has(.motile-textarea:not(:placeholder-shown)) .motile-textarea__label--error{color:#ef4444}.motile-textarea.motile-textarea--with-label{padding-top:12px;padding-bottom:12px}@media (max-width: 768px){.motile-textarea__label{font-size:16px;left:12px;top:16px}.motile-textarea-wrapper:has(.motile-textarea:focus) .motile-textarea__label,.motile-textarea-wrapper:has(.motile-textarea:not(:placeholder-shown)) .motile-textarea__label{font-size:12px}}.motile-textarea{scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.2) transparent}.motile-textarea::-webkit-scrollbar{width:6px}.motile-textarea::-webkit-scrollbar-track{background:transparent}.motile-textarea::-webkit-scrollbar-thumb{background-color:#0003;border-radius:3px;transition:background-color .2s ease}.motile-textarea::-webkit-scrollbar-thumb:hover{background-color:#0000004d}.motile-textarea::-webkit-scrollbar-thumb:active{background-color:#0006}@media (prefers-color-scheme: dark){.motile-textarea{scrollbar-color:rgba(255,255,255,.2) transparent}.motile-textarea::-webkit-scrollbar-thumb{background-color:#fff3}.motile-textarea::-webkit-scrollbar-thumb:hover{background-color:#ffffff4d}.motile-textarea::-webkit-scrollbar-thumb:active{background-color:#fff6}}
@@ -0,0 +1,111 @@
1
+ import { jsxs as h, jsx as y } from "react/jsx-runtime";
2
+ import { forwardRef as Q, useRef as U, useState as V, useMemo as X, useEffect as Z, useLayoutEffect as z } from "react";
3
+ import './Textarea.css';/* empty css */
4
+ const F = Q(
5
+ ({
6
+ autoFocus: _ = !1,
7
+ autoSelect: b = !1,
8
+ isError: T,
9
+ errorMessage: o,
10
+ className: C,
11
+ value: c,
12
+ color: R,
13
+ style: j,
14
+ maxLength: m,
15
+ label: a,
16
+ placeholder: v,
17
+ rows: d = 4,
18
+ resize: I = "none",
19
+ autoSize: n = !1,
20
+ ...H
21
+ }, S) => {
22
+ const E = U(null), i = S || E, [f, W] = V({ height: void 0, isMaxHeight: !1 }), p = T ?? !!o, t = X(() => typeof n == "boolean" ? n ? { minRows: d, maxRows: void 0 } : void 0 : n ? {
23
+ minRows: n.minRows ?? d,
24
+ maxRows: n.maxRows
25
+ } : void 0, [n, d]);
26
+ Z(() => {
27
+ if (_ && i.current) {
28
+ const s = setTimeout(() => {
29
+ i.current && (i.current.focus(), b && i.current.select());
30
+ }, 50);
31
+ return () => clearTimeout(s);
32
+ }
33
+ }, [_, b]), z(() => {
34
+ if (!t || !i.current) return;
35
+ const s = i.current;
36
+ s.style.height = "auto";
37
+ const J = s.scrollHeight, l = window.getComputedStyle(s), B = parseInt(l.lineHeight, 10), K = parseInt(l.paddingTop, 10), L = parseInt(l.paddingBottom, 10), M = parseInt(l.borderTopWidth, 10), O = parseInt(l.borderBottomWidth, 10), N = K + L + M + O, g = t.minRows ? B * t.minRows + N : void 0, u = t.maxRows ? B * t.maxRows + N : void 0;
38
+ let r = J, w = !1;
39
+ g !== void 0 && r < g && (r = g), u !== void 0 && r > u && (r = u, w = !0), s.style.height = `${r}px`, W(($) => r !== $.height || w !== $.isMaxHeight ? { height: r, isMaxHeight: w } : $);
40
+ }, [c, t]);
41
+ const e = "motile-textarea", k = [
42
+ e,
43
+ p && `${e}--error`,
44
+ p && `${e}--shake`,
45
+ a && `${e}--with-label`,
46
+ C
47
+ ].filter(Boolean).join(" "), D = [
48
+ `${e}-wrapper`,
49
+ a && `${e}-wrapper--with-label`
50
+ ].filter(Boolean).join(" "), P = [
51
+ `${e}__label`,
52
+ p && `${e}__label--error`
53
+ ].filter(Boolean).join(" "), Y = R ? { "--motile-textarea-color": R } : void 0, q = {
54
+ ...j,
55
+ resize: t ? "none" : I,
56
+ ...t ? {
57
+ height: f.height !== void 0 ? f.height : "auto",
58
+ minHeight: "auto",
59
+ overflowY: f.isMaxHeight ? "auto" : "hidden"
60
+ } : {}
61
+ }, A = c ? String(c).length : 0, x = m !== void 0, G = [
62
+ H["aria-describedby"],
63
+ o ? `${e}-error` : void 0
64
+ ].filter(Boolean).join(" ") || void 0;
65
+ return /* @__PURE__ */ h("div", { className: `${e}-root`, children: [
66
+ /* @__PURE__ */ h("div", { className: D, style: Y, children: [
67
+ a && /* @__PURE__ */ y("label", { className: P, children: a }),
68
+ /* @__PURE__ */ y(
69
+ "textarea",
70
+ {
71
+ ...H,
72
+ "aria-describedby": G,
73
+ ref: i,
74
+ className: k,
75
+ value: c,
76
+ maxLength: m,
77
+ rows: d,
78
+ style: q,
79
+ placeholder: a ? v || " " : v
80
+ }
81
+ )
82
+ ] }),
83
+ (o || x) && /* @__PURE__ */ h(
84
+ "div",
85
+ {
86
+ className: `${e}__helper-text ${o && x ? `${e}__helper-text--both` : o ? `${e}__helper-text--error-only` : `${e}__helper-text--counter-only`}`,
87
+ children: [
88
+ o && /* @__PURE__ */ y(
89
+ "span",
90
+ {
91
+ id: `${e}-error`,
92
+ className: `${e}__error-message`,
93
+ role: "alert",
94
+ children: o
95
+ }
96
+ ),
97
+ x && /* @__PURE__ */ h("span", { className: `${e}__counter`, children: [
98
+ A,
99
+ "/",
100
+ m
101
+ ] })
102
+ ]
103
+ }
104
+ )
105
+ ] });
106
+ }
107
+ );
108
+ F.displayName = "Textarea";
109
+ export {
110
+ F as Textarea
111
+ };
@@ -0,0 +1 @@
1
+ .motile-toast-container{position:fixed;pointer-events:none;display:flex;flex-direction:column;gap:8px}.motile-toast-container{top:0;left:0;right:0;align-items:center;padding:calc(env(safe-area-inset-top,0px) + 16px) 16px 16px 16px}@media (min-width: 768px){.motile-toast-container{top:0;left:auto;right:0;align-items:flex-end;padding:16px;max-width:400px}}.motile-toast{pointer-events:auto;display:inline-flex;align-items:flex-start;width:calc(100vw - 32px);min-width:200px;padding:12px 16px;background:#000000d9;border-radius:8px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 2px 8px #00000026;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;-webkit-font-smoothing:antialiased;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;will-change:transform,opacity;animation:slideDown .3s ease-out}@media (min-width: 768px){.motile-toast{width:auto;max-width:320px;animation:slideInRight .3s ease-out}}.motile-toast--exiting{animation:fadeOut .15s ease-out forwards}.motile-toast__icon{flex-shrink:0;width:18px;height:18px;display:flex;align-items:center;justify-content:center;color:#fff;margin-right:8px;margin-top:1px}.motile-toast--success .motile-toast__icon{color:#4ade80}.motile-toast--error .motile-toast__icon{color:#f87171}.motile-toast--warning .motile-toast__icon{color:#fbbf24}.motile-toast--info .motile-toast__icon{color:#60a5fa}.motile-toast__message{flex:1;min-width:0;font-size:14px;font-weight:500;line-height:1.4;color:#fff;word-wrap:break-word;word-break:break-word;overflow-wrap:break-word}@keyframes slideDown{0%{opacity:0;transform:translateY(-16px)}to{opacity:1;transform:translateY(0)}}@keyframes slideInRight{0%{opacity:0;transform:translate(16px)}to{opacity:1;transform:translate(0)}}@keyframes fadeOut{to{opacity:0;transform:scale(.95)}}@media (prefers-color-scheme: dark){.motile-toast{background:#fffffff2}.motile-toast__message,.motile-toast__icon{color:#18181b}.motile-toast--success .motile-toast__icon{color:#22c55e}.motile-toast--error .motile-toast__icon{color:#ef4444}.motile-toast--warning .motile-toast__icon{color:#f59e0b}.motile-toast--info .motile-toast__icon{color:#3b82f6}}@media (prefers-reduced-motion: reduce){.motile-toast{animation:none!important}}.motile-toast *{user-select:none;-webkit-user-select:none}
@@ -0,0 +1,178 @@
1
+ import { jsxs as s, jsx as t } from "react/jsx-runtime";
2
+ import { useState as x, useEffect as g, useCallback as w, useMemo as p, createContext as L, useContext as y } from "react";
3
+ import { createPortal as I } from "react-dom";
4
+ import './Toast.css';/* empty css */
5
+ const C = L(null);
6
+ function V() {
7
+ const e = y(C);
8
+ if (!e)
9
+ throw new Error("useToastContext must be used within ToastProvider");
10
+ return e;
11
+ }
12
+ function $({ toast: e, onRemove: a }) {
13
+ const [o, c] = x(!1), l = w(() => {
14
+ c(!0), setTimeout(() => {
15
+ a(e.id);
16
+ }, 250);
17
+ }, [e.id, a]);
18
+ g(() => {
19
+ const h = setTimeout(l, e.duration);
20
+ return () => {
21
+ clearTimeout(h);
22
+ };
23
+ }, [l, e.duration]);
24
+ const d = p(() => e.variant === "success" ? /* @__PURE__ */ s(
25
+ "svg",
26
+ {
27
+ width: "20",
28
+ height: "20",
29
+ viewBox: "0 0 20 20",
30
+ fill: "none",
31
+ xmlns: "http://www.w3.org/2000/svg",
32
+ children: [
33
+ /* @__PURE__ */ t("circle", { cx: "10", cy: "10", r: "9", fill: "currentColor", opacity: "0.2" }),
34
+ /* @__PURE__ */ t(
35
+ "path",
36
+ {
37
+ d: "M6 10L8.5 12.5L14 7",
38
+ stroke: "currentColor",
39
+ strokeWidth: "2",
40
+ strokeLinecap: "round",
41
+ strokeLinejoin: "round"
42
+ }
43
+ )
44
+ ]
45
+ }
46
+ ) : e.variant === "error" ? /* @__PURE__ */ s(
47
+ "svg",
48
+ {
49
+ width: "20",
50
+ height: "20",
51
+ viewBox: "0 0 20 20",
52
+ fill: "none",
53
+ xmlns: "http://www.w3.org/2000/svg",
54
+ children: [
55
+ /* @__PURE__ */ t("circle", { cx: "10", cy: "10", r: "9", fill: "currentColor", opacity: "0.2" }),
56
+ /* @__PURE__ */ t(
57
+ "path",
58
+ {
59
+ d: "M7 7L13 13M13 7L7 13",
60
+ stroke: "currentColor",
61
+ strokeWidth: "2",
62
+ strokeLinecap: "round"
63
+ }
64
+ )
65
+ ]
66
+ }
67
+ ) : e.variant === "warning" ? /* @__PURE__ */ s(
68
+ "svg",
69
+ {
70
+ width: "20",
71
+ height: "20",
72
+ viewBox: "0 0 20 20",
73
+ fill: "none",
74
+ xmlns: "http://www.w3.org/2000/svg",
75
+ children: [
76
+ /* @__PURE__ */ t("path", { d: "M10 2L2 17H18L10 2Z", fill: "currentColor", opacity: "0.2" }),
77
+ /* @__PURE__ */ t(
78
+ "path",
79
+ {
80
+ d: "M10 7V11M10 14V14.5",
81
+ stroke: "currentColor",
82
+ strokeWidth: "2",
83
+ strokeLinecap: "round"
84
+ }
85
+ )
86
+ ]
87
+ }
88
+ ) : e.variant === "info" ? /* @__PURE__ */ s(
89
+ "svg",
90
+ {
91
+ width: "20",
92
+ height: "20",
93
+ viewBox: "0 0 20 20",
94
+ fill: "none",
95
+ xmlns: "http://www.w3.org/2000/svg",
96
+ children: [
97
+ /* @__PURE__ */ t("circle", { cx: "10", cy: "10", r: "9", fill: "currentColor", opacity: "0.2" }),
98
+ /* @__PURE__ */ t(
99
+ "path",
100
+ {
101
+ d: "M10 7V7.5M10 10V14",
102
+ stroke: "currentColor",
103
+ strokeWidth: "2",
104
+ strokeLinecap: "round"
105
+ }
106
+ )
107
+ ]
108
+ }
109
+ ) : null, [e.variant]), n = "motile-toast", u = [
110
+ n,
111
+ `${n}--${e.variant}`,
112
+ o && `${n}--exiting`
113
+ ].filter(Boolean).join(" ");
114
+ return /* @__PURE__ */ s(
115
+ "div",
116
+ {
117
+ className: u,
118
+ role: "status",
119
+ "aria-live": "polite",
120
+ "aria-atomic": "true",
121
+ "data-toast-id": e.id,
122
+ children: [
123
+ d && /* @__PURE__ */ t("div", { className: `${n}__icon`, children: d }),
124
+ /* @__PURE__ */ t("div", { className: `${n}__message`, children: e.message })
125
+ ]
126
+ }
127
+ );
128
+ }
129
+ function j({ children: e, zIndex: a = 9999 }) {
130
+ const [o, c] = x([]), [l, d] = x(!1);
131
+ g(() => {
132
+ d(!0);
133
+ }, []);
134
+ const n = w(
135
+ (r, m = "default", i) => {
136
+ const f = `toast-${Date.now()}-${Math.random()}`, T = {
137
+ id: f,
138
+ message: r,
139
+ variant: m,
140
+ duration: (i == null ? void 0 : i.duration) ?? 4e3,
141
+ zIndex: i == null ? void 0 : i.zIndex,
142
+ createdAt: Date.now()
143
+ };
144
+ return c((M) => [T, ...M]), f;
145
+ },
146
+ []
147
+ ), u = w((r) => {
148
+ c((m) => m.filter((i) => i.id !== r));
149
+ }, []), h = p(
150
+ () => ({
151
+ toasts: o,
152
+ addToast: n
153
+ }),
154
+ [o, n]
155
+ ), v = o.filter(
156
+ (r) => r.zIndex !== void 0
157
+ ), k = v.length > 0 ? Math.max(...v.map((r) => r.zIndex)) : a;
158
+ return /* @__PURE__ */ s(C.Provider, { value: h, children: [
159
+ e,
160
+ l && I(
161
+ /* @__PURE__ */ t(
162
+ "div",
163
+ {
164
+ className: "motile-toast-container",
165
+ "aria-live": "polite",
166
+ "aria-label": "Notifications",
167
+ style: { zIndex: k },
168
+ children: o.map((r) => /* @__PURE__ */ t($, { toast: r, onRemove: u }, r.id))
169
+ }
170
+ ),
171
+ document.body
172
+ )
173
+ ] });
174
+ }
175
+ export {
176
+ j as ToastProvider,
177
+ V as useToastContext
178
+ };
@@ -0,0 +1,30 @@
1
+ import { useCallback as o } from "react";
2
+ import { useToastContext as i } from "./Toast.js";
3
+ function d() {
4
+ const { addToast: r } = i(), s = o(
5
+ (t, n) => r(t, "default", n),
6
+ [r]
7
+ ), e = o(
8
+ (t, n) => r(t, "success", n),
9
+ [r]
10
+ ), u = o(
11
+ (t, n) => r(t, "error", n),
12
+ [r]
13
+ ), c = o(
14
+ (t, n) => r(t, "warning", n),
15
+ [r]
16
+ ), a = o(
17
+ (t, n) => r(t, "info", n),
18
+ [r]
19
+ );
20
+ return {
21
+ show: s,
22
+ success: e,
23
+ error: u,
24
+ warning: c,
25
+ info: a
26
+ };
27
+ }
28
+ export {
29
+ d as useToast
30
+ };
@@ -0,0 +1 @@
1
+ .motile-tooltip-trigger{position:relative;display:inline-block;line-height:normal;vertical-align:middle}.motile-tooltip-bubble{position:fixed;z-index:2147483647;padding:8px 12px;border-radius:8px;font-size:14px;font-weight:500;line-height:1.4;box-shadow:0 6px 20px #0003;opacity:0;pointer-events:none;transition:opacity .2s cubic-bezier(.16,1,.3,1),transform .2s cubic-bezier(.16,1,.3,1)}.motile-tooltip-bubble[data-placement=top]{transform:translateY(8px) scale(.96)}.motile-tooltip-bubble[data-placement=bottom]{transform:translateY(-8px) scale(.96)}.motile-tooltip-bubble[data-placement=left]{transform:translate(8px) scale(.96)}.motile-tooltip-bubble[data-placement=right]{transform:translate(-8px) scale(.96)}.motile-tooltip-bubble[data-open=true]{opacity:1;transform:translate(0) scale(1)}.motile-tooltip-bubble[data-keep-open]{pointer-events:auto}.motile-tooltip-bubble--filled{--arrow-color: var( --motile-tooltip-color, var(--motile-ui-tooltip, rgba(0, 0, 0, .9)) );background:var(--arrow-color);color:#fff}.motile-tooltip-bubble--outlined{--arrow-color: var(--motile-tooltip-color, var(--motile-ui-tooltip, #3b82f6));background:#fff;color:var(--arrow-color);border:1px solid var(--arrow-color)}.motile-tooltip-bubble.measuring{visibility:hidden!important;opacity:1!important;max-width:none!important;max-height:none!important;left:0!important;top:0!important}.motile-tooltip-arrow{position:absolute;pointer-events:none;z-index:1}.motile-tooltip-bubble[data-placement=top] .motile-tooltip-arrow{bottom:-7.25px;left:var(--arrow-offset, 50%);transform:translate(-50%) rotate(180deg)}.motile-tooltip-bubble[data-placement=bottom] .motile-tooltip-arrow{top:-7px;left:var(--arrow-offset, 50%);transform:translate(-50%) rotate(0)}.motile-tooltip-bubble[data-placement=left] .motile-tooltip-arrow{right:-9.25px;top:var(--arrow-offset, 50%);transform:translateY(-50%) rotate(90deg)}.motile-tooltip-bubble[data-placement=right] .motile-tooltip-arrow{left:-9.25px;top:var(--arrow-offset, 50%);transform:translateY(-50%) rotate(-90deg)}
@@ -0,0 +1,321 @@
1
+ import { jsxs as tt, jsx as W } from "react/jsx-runtime";
2
+ import et, { useState as A, useEffect as H, useCallback as T, useId as ot, useRef as I, useLayoutEffect as nt, createContext as rt, useContext as it } from "react";
3
+ import { createPortal as st } from "react-dom";
4
+ import { Slot as at } from "../../utils/Slot.js";
5
+ import { FloatingArrow as lt } from "../../utils/FloatingArrow.js";
6
+ import './Tooltip.css';/* empty css */
7
+ const G = rt(null);
8
+ function X() {
9
+ const t = it(G);
10
+ if (!t)
11
+ throw new Error("Tooltip components must be used within Tooltip.Root");
12
+ return t;
13
+ }
14
+ const s = 8;
15
+ function D(t, e, r, i, a, m, u) {
16
+ switch (t) {
17
+ case "top":
18
+ return e.top - a.top - i >= s;
19
+ case "bottom":
20
+ return e.bottom + a.bottom + i <= u - s;
21
+ case "left":
22
+ return e.left - a.left - r >= s;
23
+ case "right":
24
+ return e.right + a.right + r <= m - s;
25
+ }
26
+ }
27
+ function ct(t) {
28
+ return [{
29
+ top: "bottom",
30
+ bottom: "top",
31
+ left: "right",
32
+ right: "left"
33
+ }[t]];
34
+ }
35
+ function ut(t, e, r, i) {
36
+ if (!(r < 768))
37
+ return ct(t);
38
+ const u = e.top + e.height / 2 < i / 2;
39
+ return t === "left" || t === "right" ? [u ? "bottom" : "top", u ? "top" : "bottom", t === "left" ? "right" : "left"] : t === "top" || t === "bottom" ? [t === "top" ? "bottom" : "top"] : [];
40
+ }
41
+ function pt(t, e, r, i) {
42
+ const a = {
43
+ top: t.top - e.top - s,
44
+ bottom: i - t.bottom - e.bottom - s,
45
+ left: t.left - e.left - s,
46
+ right: r - t.right - e.right - s
47
+ };
48
+ let m = "bottom", u = a.bottom;
49
+ for (const [n, l] of Object.entries(a))
50
+ l > u && (u = l, m = n);
51
+ return m;
52
+ }
53
+ function ft({
54
+ children: t,
55
+ position: e = "top",
56
+ align: r = "center",
57
+ variant: i = "filled",
58
+ color: a,
59
+ showArrow: m = !1,
60
+ keepOpen: u = !1,
61
+ offset: n
62
+ }) {
63
+ const l = n === void 0 ? { top: 7, bottom: 6, left: 6, right: 6 } : typeof n == "number" ? { top: n, bottom: n, left: n, right: n } : {
64
+ top: n.top ?? 7,
65
+ bottom: n.bottom ?? 6,
66
+ left: n.left ?? 6,
67
+ right: n.right ?? 6
68
+ }, k = ot().replace(/:/g, ""), w = I(null), x = I(null), p = I(), [b, N] = A(!1), [P, Z] = A(e), [J, K] = A({}), F = I(null), B = T((M, E = 0) => {
69
+ p.current && (clearTimeout(p.current), p.current = void 0), !M && E > 0 ? p.current = window.setTimeout(
70
+ () => N(!1),
71
+ E
72
+ ) : N(M);
73
+ }, []);
74
+ nt(() => {
75
+ if (!b || !w.current || !x.current) return;
76
+ const M = () => {
77
+ if (!w.current || !x.current) return;
78
+ const o = w.current.getBoundingClientRect(), y = x.current;
79
+ y.classList.add("measuring"), y.offsetHeight;
80
+ const $ = window.getComputedStyle(y), V = parseFloat($.width), Y = parseFloat($.height);
81
+ let c = V, d = Y;
82
+ y.classList.remove("measuring");
83
+ const R = window.innerWidth, O = window.innerHeight;
84
+ (isNaN(c) || c <= 0) && (c = 100), (isNaN(d) || d <= 0) && (d = 50);
85
+ const _ = R - s * 2, z = O - s * 2;
86
+ c > _ && (c = _), d > z && (d = z);
87
+ let v = e;
88
+ if (o.width === 0 && o.height === 0 || D(e, o, c, d, l, R, O))
89
+ v = e;
90
+ else {
91
+ const L = ut(e, o, R, O);
92
+ let q = !1;
93
+ for (const U of L)
94
+ if (D(U, o, c, d, l, R, O)) {
95
+ v = U, q = !0;
96
+ break;
97
+ }
98
+ q || (v = pt(o, l, R, O));
99
+ }
100
+ let f = 0, g = 0;
101
+ if (v === "top" || v === "bottom") {
102
+ switch (r) {
103
+ case "start":
104
+ f = o.left;
105
+ break;
106
+ case "center":
107
+ f = o.left + o.width / 2 - c / 2;
108
+ break;
109
+ case "end":
110
+ f = o.right - c;
111
+ break;
112
+ }
113
+ f = Math.max(s, Math.min(f, R - s - c)), g = v === "top" ? o.top - l.top - d : o.bottom + l.bottom, g = Math.max(s, Math.min(g, O - s - d));
114
+ } else {
115
+ switch (r) {
116
+ case "start":
117
+ g = o.top;
118
+ break;
119
+ case "center":
120
+ g = o.top + o.height / 2 - d / 2;
121
+ break;
122
+ case "end":
123
+ g = o.bottom - d;
124
+ break;
125
+ }
126
+ g = Math.max(s, Math.min(g, O - s - d)), v === "left" ? (f = o.left - l.left - c, f < s && (c = o.left - l.left - s, f = s)) : (f = o.right + l.right, f + c > R - s && (c = R - s - f));
127
+ }
128
+ let h = 0;
129
+ const S = 12, C = 16;
130
+ if (v === "left" || v === "right") {
131
+ switch (r) {
132
+ case "start":
133
+ h = o.top - g + S;
134
+ break;
135
+ case "center":
136
+ h = o.top + o.height / 2 - g;
137
+ break;
138
+ case "end":
139
+ h = o.bottom - g - S;
140
+ break;
141
+ }
142
+ const L = Math.max(C, d - C);
143
+ h = Math.max(
144
+ C,
145
+ Math.min(h, L)
146
+ );
147
+ } else {
148
+ switch (r) {
149
+ case "start":
150
+ h = o.left - f + S;
151
+ break;
152
+ case "center":
153
+ h = o.left + o.width / 2 - f;
154
+ break;
155
+ case "end":
156
+ h = o.right - f - S;
157
+ break;
158
+ }
159
+ const L = Math.max(C, c - C);
160
+ h = Math.max(
161
+ C,
162
+ Math.min(h, L)
163
+ );
164
+ }
165
+ isNaN(h) && (h = C), Z(v), K({
166
+ left: Math.round(f),
167
+ top: Math.round(g),
168
+ ...c !== V && { maxWidth: c },
169
+ ...d !== Y && { maxHeight: z },
170
+ "--arrow-offset": `${Math.round(h)}px`,
171
+ ...a && { "--motile-tooltip-color": a }
172
+ });
173
+ }, E = () => {
174
+ F.current === null && (F.current = requestAnimationFrame(() => {
175
+ M(), F.current = null;
176
+ }));
177
+ };
178
+ M(), window.addEventListener("scroll", E, {
179
+ passive: !0,
180
+ capture: !0
181
+ }), window.addEventListener("resize", E, { passive: !0 });
182
+ const j = new ResizeObserver(E);
183
+ return w.current && j.observe(w.current), () => {
184
+ F.current !== null && (cancelAnimationFrame(F.current), F.current = null), window.removeEventListener("scroll", E, { capture: !0 }), window.removeEventListener("resize", E), j.disconnect();
185
+ };
186
+ }, [b, e, r, a, n]), H(() => {
187
+ if (!b) return;
188
+ const M = () => {
189
+ B(!1, 0);
190
+ };
191
+ return window.addEventListener("scroll", M, { capture: !0 }), () => {
192
+ window.removeEventListener("scroll", M, { capture: !0 });
193
+ };
194
+ }, [b, B]), H(() => () => {
195
+ p.current && clearTimeout(p.current);
196
+ }, []);
197
+ const Q = {
198
+ open: b,
199
+ setOpen: B,
200
+ position: e,
201
+ align: r,
202
+ variant: i,
203
+ showArrow: m,
204
+ color: a,
205
+ keepOpen: u,
206
+ tooltipId: `${k}-tooltip`,
207
+ triggerRef: w,
208
+ contentRef: x,
209
+ style: J,
210
+ placement: P
211
+ };
212
+ return /* @__PURE__ */ W(G.Provider, { value: Q, children: t });
213
+ }
214
+ function mt({ children: t, asChild: e = !1 }) {
215
+ const { open: r, setOpen: i, tooltipId: a, triggerRef: m, keepOpen: u } = X(), n = T(() => {
216
+ i(!0, 0);
217
+ }, [i]), l = T(() => {
218
+ u ? i(!1, 100) : i(!1, 0);
219
+ }, [i, u]), k = T(() => {
220
+ i(!0, 0);
221
+ }, [i]), w = T(() => {
222
+ i(!1, 0);
223
+ }, [i]), x = T(() => {
224
+ i(!r, 0);
225
+ }, [i, r]);
226
+ return e ? /* @__PURE__ */ W(
227
+ at,
228
+ {
229
+ ref: (p) => {
230
+ m.current = p;
231
+ },
232
+ className: "motile-tooltip-trigger",
233
+ "aria-describedby": r ? a : void 0,
234
+ tabIndex: 0,
235
+ onMouseEnter: n,
236
+ onMouseLeave: l,
237
+ onFocus: k,
238
+ onBlur: w,
239
+ onClick: x,
240
+ children: t
241
+ }
242
+ ) : et.cloneElement(t, {
243
+ ref: (p) => {
244
+ m.current = p;
245
+ const b = t.props.ref || t.ref;
246
+ b && (typeof b == "function" ? b(p) : typeof b == "object" && b !== null && (b.current = p));
247
+ },
248
+ className: `motile-tooltip-trigger ${t.props.className || ""}`.trim(),
249
+ "aria-describedby": r ? a : void 0,
250
+ tabIndex: t.props.tabIndex ?? 0,
251
+ onMouseEnter: n,
252
+ onMouseLeave: l,
253
+ onFocus: k,
254
+ onBlur: w,
255
+ onClick: x
256
+ });
257
+ }
258
+ function bt({ children: t }) {
259
+ const {
260
+ open: e,
261
+ setOpen: r,
262
+ tooltipId: i,
263
+ contentRef: a,
264
+ variant: m,
265
+ showArrow: u,
266
+ keepOpen: n,
267
+ align: l,
268
+ style: k,
269
+ placement: w
270
+ } = X(), [x, p] = A(!1);
271
+ H(() => {
272
+ e ? requestAnimationFrame(() => {
273
+ p(!0);
274
+ }) : p(!1);
275
+ }, [e]);
276
+ const b = T(() => {
277
+ n && r(!0, 0);
278
+ }, [n, r]), N = T(() => {
279
+ n && r(!1, 0);
280
+ }, [n, r]), P = k["--motile-tooltip-color"] || (m === "filled" ? "var(--motile-ui-tooltip, rgba(0, 0, 0, 0.9))" : "var(--motile-ui-tooltip, #3b82f6)");
281
+ return !e || typeof document > "u" ? null : st(
282
+ /* @__PURE__ */ tt(
283
+ "div",
284
+ {
285
+ ref: a,
286
+ id: i,
287
+ role: "tooltip",
288
+ className: `motile-tooltip-bubble motile-tooltip-bubble--${m}`,
289
+ "data-open": x || void 0,
290
+ "data-placement": w,
291
+ "data-align": l,
292
+ "data-show-arrow": u || void 0,
293
+ "data-keep-open": n || void 0,
294
+ style: k,
295
+ "aria-hidden": !e,
296
+ onMouseEnter: b,
297
+ onMouseLeave: N,
298
+ children: [
299
+ t,
300
+ u && /* @__PURE__ */ W(
301
+ lt,
302
+ {
303
+ className: "motile-tooltip-arrow",
304
+ variant: m,
305
+ color: P
306
+ }
307
+ )
308
+ ]
309
+ }
310
+ ),
311
+ document.body
312
+ );
313
+ }
314
+ const Mt = {
315
+ Root: ft,
316
+ Trigger: mt,
317
+ Content: bt
318
+ };
319
+ export {
320
+ Mt as Tooltip
321
+ };