@jonmilner/ui 0.0.0-stage → 0.1.1

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 (215) hide show
  1. package/THIRD_PARTY_NOTICES.md +51 -0
  2. package/dist/AlertDialog/index.d.mts +21 -0
  3. package/dist/AlertDialog/index.mjs +29 -0
  4. package/dist/Badge/Badge.css +2 -0
  5. package/dist/Badge/Badge.css.mjs +24 -0
  6. package/dist/Badge/index.d.mts +11 -0
  7. package/dist/Badge/index.mjs +54 -0
  8. package/dist/Box/Box.css +2 -0
  9. package/dist/Box/Box.css.mjs +8 -0
  10. package/dist/Box/index.d.mts +8 -0
  11. package/dist/Box/index.mjs +15 -0
  12. package/dist/Button/Button.css +2 -0
  13. package/dist/Button/Button.css.mjs +25 -0
  14. package/dist/Button/index.d.mts +18 -0
  15. package/dist/Button/index.mjs +97 -0
  16. package/dist/Checkbox/Checkbox.css +2 -0
  17. package/dist/Checkbox/Checkbox.css.mjs +8 -0
  18. package/dist/Checkbox/index.d.mts +6 -0
  19. package/dist/Checkbox/index.mjs +45 -0
  20. package/dist/Chip/Chip.css +2 -0
  21. package/dist/Chip/Chip.css.mjs +17 -0
  22. package/dist/Chip/index.d.mts +13 -0
  23. package/dist/Chip/index.mjs +73 -0
  24. package/dist/Clickable/Clickable.css +2 -0
  25. package/dist/Clickable/Clickable.css.mjs +8 -0
  26. package/dist/Clickable/index.d.mts +11 -0
  27. package/dist/Clickable/index.mjs +28 -0
  28. package/dist/Dialog/Dialog.css +2 -0
  29. package/dist/Dialog/Dialog.css.d.mts +3 -0
  30. package/dist/Dialog/Dialog.css.mjs +12 -0
  31. package/dist/Dialog/client.d.mts +12 -0
  32. package/dist/Dialog/client.mjs +31 -0
  33. package/dist/Dialog/index.d.mts +30 -0
  34. package/dist/Dialog/index.mjs +85 -0
  35. package/dist/Field/Field.css +2 -0
  36. package/dist/Field/Field.css.mjs +8 -0
  37. package/dist/Field/client.mjs +26 -0
  38. package/dist/Field/index.d.mts +20 -0
  39. package/dist/Field/index.mjs +88 -0
  40. package/dist/Heading/Heading.css +2 -0
  41. package/dist/Heading/Heading.css.mjs +8 -0
  42. package/dist/Heading/index.d.mts +9 -0
  43. package/dist/Heading/index.mjs +27 -0
  44. package/dist/Icon/Icon.css +2 -0
  45. package/dist/Icon/Icon.css.mjs +17 -0
  46. package/dist/Icon/index.d.mts +12 -0
  47. package/dist/Icon/index.mjs +24 -0
  48. package/dist/IconButton/IconButton.css +2 -0
  49. package/dist/IconButton/IconButton.css.mjs +24 -0
  50. package/dist/IconButton/index.d.mts +15 -0
  51. package/dist/IconButton/index.mjs +25 -0
  52. package/dist/Inline/Inline.css +2 -0
  53. package/dist/Inline/Inline.css.mjs +8 -0
  54. package/dist/Inline/index.d.mts +14 -0
  55. package/dist/Inline/index.mjs +17 -0
  56. package/dist/Menu/Menu.css +2 -0
  57. package/dist/Menu/Menu.css.mjs +8 -0
  58. package/dist/Menu/client.d.mts +9 -0
  59. package/dist/Menu/client.mjs +27 -0
  60. package/dist/Menu/index.d.mts +34 -0
  61. package/dist/Menu/index.mjs +107 -0
  62. package/dist/MultiSelect/MultiSelect.css +2 -0
  63. package/dist/MultiSelect/MultiSelect.css.mjs +8 -0
  64. package/dist/MultiSelect/client.d.mts +8 -0
  65. package/dist/MultiSelect/client.mjs +93 -0
  66. package/dist/MultiSelect/index.d.mts +23 -0
  67. package/dist/MultiSelect/index.mjs +75 -0
  68. package/dist/SearchField/SearchField.css +2 -0
  69. package/dist/SearchField/SearchField.css.mjs +27 -0
  70. package/dist/SearchField/client.d.mts +5 -0
  71. package/dist/SearchField/client.mjs +74 -0
  72. package/dist/SearchField/index.d.mts +25 -0
  73. package/dist/SearchField/index.mjs +36 -0
  74. package/dist/Stack/Stack.css +2 -0
  75. package/dist/Stack/Stack.css.mjs +8 -0
  76. package/dist/Stack/index.d.mts +14 -0
  77. package/dist/Stack/index.mjs +15 -0
  78. package/dist/Tabs/Tabs.css +2 -0
  79. package/dist/Tabs/Tabs.css.mjs +8 -0
  80. package/dist/Tabs/index.d.mts +20 -0
  81. package/dist/Tabs/index.mjs +88 -0
  82. package/dist/Tag/Tag.css +2 -0
  83. package/dist/Tag/Tag.css.mjs +17 -0
  84. package/dist/Tag/index.d.mts +13 -0
  85. package/dist/Tag/index.mjs +82 -0
  86. package/dist/Text/Text.css +2 -0
  87. package/dist/Text/Text.css.mjs +32 -0
  88. package/dist/Text/index.d.mts +16 -0
  89. package/dist/Text/index.mjs +25 -0
  90. package/dist/Toast/Toast.css +2 -0
  91. package/dist/Toast/Toast.css.mjs +18 -0
  92. package/dist/Toast/client.d.mts +46 -0
  93. package/dist/Toast/client.mjs +219 -0
  94. package/dist/Toast/index.d.mts +7 -0
  95. package/dist/Toast/index.mjs +5 -0
  96. package/dist/base.css +6 -0
  97. package/dist/brands/brand.d.mts +9 -0
  98. package/dist/brands/brand.mjs +4 -0
  99. package/dist/brands/check-fonts.mjs +15 -0
  100. package/dist/brands/default.d.mts +4 -0
  101. package/dist/brands/default.mjs +74 -0
  102. package/dist/brands/font.d.mts +17 -0
  103. package/dist/brands/font.mjs +35 -0
  104. package/dist/brands/forced-colors.mjs +18 -0
  105. package/dist/brands/index.d.mts +8 -0
  106. package/dist/brands/index.mjs +5 -0
  107. package/dist/brands/metrics.mjs +40 -0
  108. package/dist/contrast/color.d.mts +3 -0
  109. package/dist/contrast/color.mjs +222 -0
  110. package/dist/contrast/contrast.d.mts +18 -0
  111. package/dist/contrast/contrast.mjs +52 -0
  112. package/dist/contrast/mixes.mjs +33 -0
  113. package/dist/docs/AlertDialog.md +113 -0
  114. package/dist/docs/Badge.md +76 -0
  115. package/dist/docs/Box.md +87 -0
  116. package/dist/docs/Button.md +98 -0
  117. package/dist/docs/Checkbox.md +107 -0
  118. package/dist/docs/Chip.md +92 -0
  119. package/dist/docs/Clickable.md +82 -0
  120. package/dist/docs/Dialog.md +166 -0
  121. package/dist/docs/Field.md +143 -0
  122. package/dist/docs/Heading.md +69 -0
  123. package/dist/docs/Icon.md +116 -0
  124. package/dist/docs/IconButton.md +83 -0
  125. package/dist/docs/Inline.md +79 -0
  126. package/dist/docs/Menu.md +181 -0
  127. package/dist/docs/MultiSelect.md +120 -0
  128. package/dist/docs/SearchField.md +127 -0
  129. package/dist/docs/Stack.md +79 -0
  130. package/dist/docs/Tabs.md +130 -0
  131. package/dist/docs/Tag.md +97 -0
  132. package/dist/docs/Text.md +90 -0
  133. package/dist/docs/Toast.md +115 -0
  134. package/dist/docs/llms.txt +33 -0
  135. package/dist/docs/manifest.json +2649 -0
  136. package/dist/docs/manifest.schema.json +96 -0
  137. package/dist/docs/migrations/README.md +27 -0
  138. package/dist/docs/theming.md +59 -0
  139. package/dist/icons/ArrowLeftIcon.d.mts +4 -0
  140. package/dist/icons/ArrowLeftIcon.mjs +11 -0
  141. package/dist/icons/ArrowRightIcon.d.mts +4 -0
  142. package/dist/icons/ArrowRightIcon.mjs +11 -0
  143. package/dist/icons/CheckIcon.d.mts +4 -0
  144. package/dist/icons/CheckIcon.mjs +11 -0
  145. package/dist/icons/ChevronDownIcon.d.mts +4 -0
  146. package/dist/icons/ChevronDownIcon.mjs +11 -0
  147. package/dist/icons/ChevronRightIcon.d.mts +4 -0
  148. package/dist/icons/ChevronRightIcon.mjs +11 -0
  149. package/dist/icons/CircleAlertIcon.d.mts +4 -0
  150. package/dist/icons/CircleAlertIcon.mjs +15 -0
  151. package/dist/icons/CircleCheckIcon.d.mts +4 -0
  152. package/dist/icons/CircleCheckIcon.mjs +15 -0
  153. package/dist/icons/CircleDotIcon.d.mts +4 -0
  154. package/dist/icons/CircleDotIcon.mjs +19 -0
  155. package/dist/icons/CircleSlashIcon.d.mts +4 -0
  156. package/dist/icons/CircleSlashIcon.mjs +15 -0
  157. package/dist/icons/GitMergeIcon.d.mts +4 -0
  158. package/dist/icons/GitMergeIcon.mjs +23 -0
  159. package/dist/icons/GitPullRequestClosedIcon.d.mts +4 -0
  160. package/dist/icons/GitPullRequestClosedIcon.mjs +23 -0
  161. package/dist/icons/GitPullRequestDraftIcon.d.mts +4 -0
  162. package/dist/icons/GitPullRequestDraftIcon.mjs +23 -0
  163. package/dist/icons/GitPullRequestIcon.d.mts +4 -0
  164. package/dist/icons/GitPullRequestIcon.mjs +23 -0
  165. package/dist/icons/InboxIcon.d.mts +4 -0
  166. package/dist/icons/InboxIcon.mjs +11 -0
  167. package/dist/icons/InfoIcon.d.mts +4 -0
  168. package/dist/icons/InfoIcon.mjs +15 -0
  169. package/dist/icons/LoaderCircleIcon.d.mts +4 -0
  170. package/dist/icons/LoaderCircleIcon.mjs +11 -0
  171. package/dist/icons/RefreshCwIcon.d.mts +4 -0
  172. package/dist/icons/RefreshCwIcon.mjs +15 -0
  173. package/dist/icons/SearchIcon.d.mts +4 -0
  174. package/dist/icons/SearchIcon.mjs +15 -0
  175. package/dist/icons/SettingsIcon.d.mts +4 -0
  176. package/dist/icons/SettingsIcon.mjs +15 -0
  177. package/dist/icons/XIcon.d.mts +4 -0
  178. package/dist/icons/XIcon.mjs +11 -0
  179. package/dist/icons/index.d.mts +25 -0
  180. package/dist/icons/index.mjs +45 -0
  181. package/dist/index.d.mts +28 -0
  182. package/dist/index.mjs +25 -0
  183. package/dist/popup/client.d.mts +9 -0
  184. package/dist/popup/client.mjs +31 -0
  185. package/dist/styles/atoms.css +2 -0
  186. package/dist/styles/atoms.css.d.mts +219 -0
  187. package/dist/styles/atoms.css.mjs +2669 -0
  188. package/dist/styles/button-fills.mjs +17 -0
  189. package/dist/styles/highlight.mjs +8 -0
  190. package/dist/styles/hover-tint.mjs +4 -0
  191. package/dist/styles/join.mjs +4 -0
  192. package/dist/styles/layers.css +2 -0
  193. package/dist/styles/part-props.d.mts +8 -0
  194. package/dist/styles/split-style-props.mjs +9 -0
  195. package/dist/testing/index.d.mts +4 -0
  196. package/dist/testing/index.mjs +3 -0
  197. package/dist/testing/motion.d.mts +22 -0
  198. package/dist/testing/motion.mjs +49 -0
  199. package/dist/theme/FontCheck.mjs +11 -0
  200. package/dist/theme/ThemeProvider.d.mts +15 -0
  201. package/dist/theme/ThemeProvider.mjs +23 -0
  202. package/dist/theme/define-theme.d.mts +9 -0
  203. package/dist/theme/define-theme.mjs +84 -0
  204. package/dist/theme/use-theme-container.mjs +15 -0
  205. package/dist/tokens/contract.d.mts +110 -0
  206. package/dist/tokens/contract.mjs +17 -0
  207. package/dist/tokens/index.d.mts +2 -0
  208. package/dist/tokens/index.mjs +1 -0
  209. package/dist/tokens/roles.d.mts +6 -0
  210. package/dist/tokens/roles.mjs +24 -0
  211. package/dist/tokens/scales.d.mts +100 -0
  212. package/dist/tokens/scales.mjs +103 -0
  213. package/dist/types.d.mts +7 -0
  214. package/package.json +159 -3
  215. package/README.md +0 -3
@@ -0,0 +1,74 @@
1
+ import { lightDark as e } from "./brand.mjs";
2
+ import { arial as t, courierNew as n, inter as r, jetBrainsMono as i } from "./metrics.mjs";
3
+ //#region src/brands/default.ts
4
+ var a = (e, t) => Object.fromEntries(Object.entries(t).map(([t, [n, r]]) => [t, `oklch(${n} ${r} ${e})`])), o = "oklch(1 0 0)", s = "oklch(0 0 0)", c = a(265, {
5
+ 50: [.985, .002],
6
+ 100: [.968, .004],
7
+ 200: [.925, .006],
8
+ 300: [.87, .008],
9
+ 400: [.71, .012],
10
+ 500: [.555, .014],
11
+ 600: [.445, .014],
12
+ 700: [.37, .013],
13
+ 800: [.27, .01],
14
+ 900: [.205, .008],
15
+ 950: [.145, .006]
16
+ }), l = a(258, {
17
+ 50: [.97, .014],
18
+ 100: [.932, .032],
19
+ 200: [.882, .056],
20
+ 300: [.809, .095],
21
+ 400: [.707, .14],
22
+ 500: [.623, .19],
23
+ 600: [.546, .19],
24
+ 700: [.488, .18],
25
+ 800: [.424, .155],
26
+ 900: [.379, .135],
27
+ 950: [.282, .09]
28
+ }), u = a(25, {
29
+ 50: [.971, .013],
30
+ 100: [.936, .032],
31
+ 200: [.885, .06],
32
+ 300: [.808, .105],
33
+ 400: [.704, .17],
34
+ 500: [.637, .2],
35
+ 600: [.56, .2],
36
+ 700: [.505, .19],
37
+ 800: [.444, .16],
38
+ 900: [.396, .13],
39
+ 950: [.258, .085]
40
+ }), d = {
41
+ metrics: r,
42
+ fallback: t,
43
+ generic: "sans-serif"
44
+ }, f = {
45
+ metrics: i,
46
+ fallback: n,
47
+ generic: "monospace"
48
+ }, p = {
49
+ name: "default",
50
+ color: {
51
+ bg: e(o, c[950]),
52
+ bgMuted: e(c[100], c[800]),
53
+ bgRaised: e(o, c[900]),
54
+ fg: e(c[950], c[50]),
55
+ fgMuted: e(c[600], c[400]),
56
+ border: e(c[200], c[800]),
57
+ borderStrong: e(c[500], c[500]),
58
+ accent: e(l[600], l[400]),
59
+ accentFg: e(o, c[950]),
60
+ danger: e(u[600], u[400]),
61
+ dangerFg: e(o, c[950]),
62
+ focus: e(l[600], l[400]),
63
+ shadow: e(c[950], s)
64
+ },
65
+ font: {
66
+ body: d,
67
+ heading: d,
68
+ display: d,
69
+ label: d,
70
+ mono: f
71
+ }
72
+ };
73
+ //#endregion
74
+ export { p as defaultBrand };
@@ -0,0 +1,17 @@
1
+ //#region src/brands/font.d.ts
2
+ export interface FontMetrics {
3
+ readonly familyName: string;
4
+ readonly fullName?: string;
5
+ readonly postscriptName?: string;
6
+ readonly capHeight: number;
7
+ readonly ascent: number;
8
+ readonly descent: number;
9
+ readonly lineGap: number;
10
+ readonly unitsPerEm: number;
11
+ }
12
+ export interface BrandFont {
13
+ readonly metrics: FontMetrics;
14
+ readonly fallback: FontMetrics;
15
+ readonly generic: "sans-serif" | "serif" | "monospace";
16
+ }
17
+ //#endregion
@@ -0,0 +1,35 @@
1
+ //#region src/brands/font.ts
2
+ var e = (e) => `"${e}"`, t = (e) => String(Number(e.toFixed(6))), n = (e) => `${t(e * 100)}%`, r = (e) => `${e.metrics.familyName} Fallback`, i = (t) => [
3
+ e(t.metrics.familyName),
4
+ e(r(t)),
5
+ t.generic
6
+ ].join(", ");
7
+ function a({ capHeight: e, ascent: n, descent: r, unitsPerEm: i }) {
8
+ let a = (n - Math.abs(r)) / i / 2;
9
+ return {
10
+ cap: t(e / i - a),
11
+ baseline: t(a)
12
+ };
13
+ }
14
+ var o = 1.0001;
15
+ function s({ metrics: t, fallback: r }) {
16
+ let i = t.capHeight / t.unitsPerEm / (r.capHeight / r.unitsPerEm), a = t.unitsPerEm * i, s = [r.fullName ?? r.familyName, r.postscriptName];
17
+ return {
18
+ src: [...new Set(s)].filter(Boolean).map((t) => `local(${e(t)})`).join(", "),
19
+ sizeAdjust: n(i),
20
+ ascentOverride: n(t.ascent / a * o),
21
+ descentOverride: n(Math.abs(t.descent) / a * o),
22
+ lineGapOverride: n(t.lineGap / a)
23
+ };
24
+ }
25
+ function c(e) {
26
+ let t = /* @__PURE__ */ new Map();
27
+ for (let n of e) {
28
+ let e = r(n), i = s(n), a = t.get(e);
29
+ if (a && JSON.stringify(a) !== JSON.stringify(i)) throw Error(`"${e}" is declared with different metrics or fallbacks`);
30
+ t.set(e, i);
31
+ }
32
+ return t;
33
+ }
34
+ //#endregion
35
+ export { s as fallbackFace, c as fallbackFaces, r as fallbackFamily, i as fontStack, a as fontTrim };
@@ -0,0 +1,18 @@
1
+ //#region src/brands/forced-colors.ts
2
+ var e = {
3
+ bg: "Canvas",
4
+ bgMuted: "Canvas",
5
+ bgRaised: "Canvas",
6
+ fg: "CanvasText",
7
+ fgMuted: "CanvasText",
8
+ border: "CanvasText",
9
+ borderStrong: "CanvasText",
10
+ accent: "LinkText",
11
+ accentFg: "Canvas",
12
+ danger: "CanvasText",
13
+ dangerFg: "Canvas",
14
+ focus: "Highlight",
15
+ shadow: "CanvasText"
16
+ };
17
+ //#endregion
18
+ export { e as forcedColors };
@@ -0,0 +1,8 @@
1
+ import { Brand } from "./brand.mjs";
2
+ import { defaultBrand } from "./default.mjs";
3
+ //#region src/brands/index.d.ts
4
+ export declare const presets: {
5
+ default: Brand;
6
+ };
7
+ //#endregion
8
+ export { type Brand, defaultBrand };
@@ -0,0 +1,5 @@
1
+ import { defaultBrand as e } from "./default.mjs";
2
+ //#region src/brands/index.ts
3
+ var t = { default: e };
4
+ //#endregion
5
+ export { e as defaultBrand, t as presets };
@@ -0,0 +1,40 @@
1
+ //#region src/brands/metrics.ts
2
+ var e = {
3
+ familyName: "Inter",
4
+ fullName: "Inter Regular",
5
+ postscriptName: "Inter-Regular",
6
+ capHeight: 1490,
7
+ ascent: 1984,
8
+ descent: -494,
9
+ lineGap: 0,
10
+ unitsPerEm: 2048
11
+ }, t = {
12
+ familyName: "JetBrains Mono",
13
+ fullName: "JetBrains Mono Regular",
14
+ postscriptName: "JetBrainsMono-Regular",
15
+ capHeight: 730,
16
+ ascent: 1020,
17
+ descent: -300,
18
+ lineGap: 0,
19
+ unitsPerEm: 1e3
20
+ }, n = {
21
+ familyName: "Arial",
22
+ fullName: "Arial",
23
+ postscriptName: "ArialMT",
24
+ capHeight: 1467,
25
+ ascent: 1854,
26
+ descent: -434,
27
+ lineGap: 67,
28
+ unitsPerEm: 2048
29
+ }, r = {
30
+ familyName: "Courier New",
31
+ fullName: "Courier New",
32
+ postscriptName: "CourierNewPSMT",
33
+ capHeight: 1170,
34
+ ascent: 1705,
35
+ descent: -615,
36
+ lineGap: 0,
37
+ unitsPerEm: 2048
38
+ };
39
+ //#endregion
40
+ export { n as arial, r as courierNew, e as inter, t as jetBrainsMono };
@@ -0,0 +1,3 @@
1
+ //#region src/contrast/color.d.ts
2
+ export type Mode = "light" | "dark";
3
+ //#endregion
@@ -0,0 +1,222 @@
1
+ //#region src/contrast/color.ts
2
+ var e = {
3
+ black: {
4
+ space: "srgb",
5
+ coords: [
6
+ 0,
7
+ 0,
8
+ 0
9
+ ],
10
+ alpha: 1
11
+ },
12
+ white: {
13
+ space: "srgb",
14
+ coords: [
15
+ 1,
16
+ 1,
17
+ 1
18
+ ],
19
+ alpha: 1
20
+ },
21
+ transparent: {
22
+ space: "srgb",
23
+ coords: [
24
+ 0,
25
+ 0,
26
+ 0
27
+ ],
28
+ alpha: 0
29
+ }
30
+ };
31
+ function t(e, t) {
32
+ let r = n(e.trim().toLowerCase(), t), [i, a, o] = y(r).map((e) => v(Math.min(1, Math.max(0, e))));
33
+ return {
34
+ r: i,
35
+ g: a,
36
+ b: o,
37
+ alpha: r.alpha
38
+ };
39
+ }
40
+ function n(t, s) {
41
+ if (t in e) return e[t];
42
+ if (t.startsWith("#")) return r(t);
43
+ let c = /^([a-z-]+)\((.*)\)$/s.exec(t);
44
+ if (!c) throw Error(`Unsupported color: ${t}`);
45
+ let [, l, u = ""] = c;
46
+ switch (l) {
47
+ case "light-dark": {
48
+ let [e, r] = h(u, ",", 2, t);
49
+ return n(s === "light" ? e : r, s);
50
+ }
51
+ case "color-mix": return o(u, s, t);
52
+ case "rgb":
53
+ case "rgba": return i(u, t);
54
+ case "oklab":
55
+ case "oklch": return a(l, u, t);
56
+ default: throw Error(`Unsupported color: ${t}`);
57
+ }
58
+ }
59
+ function r(e) {
60
+ let t = e.slice(1);
61
+ if (!/^([\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/.test(t)) throw Error(`Unsupported color: ${e}`);
62
+ let [n, r, i, a = 255] = (t.length <= 4 ? t.split("").map((e) => e + e) : t.match(/../g)).map((e) => Number.parseInt(e, 16));
63
+ return {
64
+ space: "srgb",
65
+ coords: [
66
+ n / 255,
67
+ r / 255,
68
+ i / 255
69
+ ],
70
+ alpha: a / 255
71
+ };
72
+ }
73
+ function i(e, t) {
74
+ let [n, r] = e.includes(",") ? (([e, t, n, r]) => [[
75
+ e,
76
+ t,
77
+ n
78
+ ], r])(h(e, ",", [3, 4], t)) : m(e, t), [i, a, o] = n.map((e) => Math.min(1, Math.max(0, u(e, 255, t) / 255)));
79
+ return {
80
+ space: "srgb",
81
+ coords: [
82
+ i,
83
+ a,
84
+ o
85
+ ],
86
+ alpha: p(r, t)
87
+ };
88
+ }
89
+ function a(e, t, n) {
90
+ let [[r, i, a], o] = m(t, n), s = Math.min(1, Math.max(0, u(r, 1, n)));
91
+ return {
92
+ space: e,
93
+ coords: e === "oklab" ? [
94
+ s,
95
+ u(i, .4, n),
96
+ u(a, .4, n)
97
+ ] : [
98
+ s,
99
+ Math.max(0, u(i, .4, n)),
100
+ f(a, n)
101
+ ],
102
+ alpha: p(o, n)
103
+ };
104
+ }
105
+ function o(e, t, n) {
106
+ let [r = "", i, a] = h(e, ",", 3, n), o = /^in (srgb|srgb-linear|oklab|oklch)( shorter hue)?$/.exec(r.trim())?.[1];
107
+ if (!o) throw Error(`Unsupported color-mix() space: ${n}`);
108
+ let [l, u] = s(i, t, n), [d, f] = s(a, t, n), p = u ?? (f === void 0 ? 50 : 100 - f), m = f ?? 100 - p, _ = p + m;
109
+ if (_ <= 0 || [p, m].some((e) => e < 0 || e > 100)) throw Error(`Invalid color-mix() percentages: ${n}`);
110
+ let v = m / _, y = g(l, o), b = g(d, o);
111
+ o === "oklch" && c(y.coords, b.coords);
112
+ let x = y.alpha * (1 - v) + b.alpha * v;
113
+ return {
114
+ space: o,
115
+ coords: y.coords.map((e, t) => {
116
+ if (o === "oklch" && t === 2) return e * (1 - v) + b.coords[t] * v;
117
+ let n = e * y.alpha * (1 - v) + b.coords[t] * b.alpha * v;
118
+ return x === 0 ? 0 : n / x;
119
+ }),
120
+ alpha: x * Math.min(1, _ / 100)
121
+ };
122
+ }
123
+ function s(e, t, r) {
124
+ let i = h(e ?? "", " ", [1, 2], r), a = i.findIndex((e) => e.endsWith("%"));
125
+ if (i.length > 2 || i.length - (a === -1 ? 0 : 1) != 1) throw Error(`Invalid color-mix() argument: ${r}`);
126
+ return [n(i[+(a === 0)], t), a === -1 ? void 0 : u(i[a], 100, r)];
127
+ }
128
+ function c(e, t) {
129
+ let n = 1e-6;
130
+ e[1] < n && t[1] >= n && (e[2] = t[2]), t[1] < n && e[1] >= n && (t[2] = e[2]);
131
+ let r = t[2] - e[2];
132
+ r > 180 ? e[2] += 360 : r < -180 && (t[2] += 360);
133
+ }
134
+ var l = /^[+-]?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?/;
135
+ function u(e, t, n) {
136
+ let r = l.exec(e ?? ""), i = e?.slice(r?.[0].length ?? 0);
137
+ if (!r || i !== "" && i !== "%") throw Error(`Invalid channel in ${n}`);
138
+ let a = Number(r[0]);
139
+ return i === "%" ? a / 100 * t : a;
140
+ }
141
+ var d = {
142
+ "": 1,
143
+ deg: 1,
144
+ grad: .9,
145
+ rad: 180 / Math.PI,
146
+ turn: 360
147
+ };
148
+ function f(e, t) {
149
+ let n = l.exec(e ?? ""), r = e?.slice(n?.[0].length ?? 0) ?? "";
150
+ if (!n || !(r in d)) throw Error(`Invalid hue in ${t}`);
151
+ return (Number(n[0]) * d[r] % 360 + 360) % 360;
152
+ }
153
+ function p(e, t) {
154
+ return e === void 0 ? 1 : Math.min(1, Math.max(0, u(e, 1, t)));
155
+ }
156
+ function m(e, t) {
157
+ let [n = "", r] = h(e, "/", [1, 2], t);
158
+ return [h(n, " ", 3, t), r];
159
+ }
160
+ function h(e, t, n, r) {
161
+ let i = [], a = 0, o = "";
162
+ for (let n of e) {
163
+ n === "(" && a++, n === ")" && a--;
164
+ let e = t === " " ? /\s/.test(n) : n === t;
165
+ a === 0 && e ? (i.push(o), o = "") : o += n;
166
+ }
167
+ i.push(o);
168
+ let s = t === " " ? i.filter(Boolean) : i.map((e) => e.trim()), c = n === void 0 ? [] : [n].flat();
169
+ if (a !== 0 || c.length && !c.includes(s.length)) throw Error(`Invalid color: ${r}`);
170
+ return s;
171
+ }
172
+ function g(e, t) {
173
+ return e.space === t ? {
174
+ ...e,
175
+ coords: [...e.coords]
176
+ } : {
177
+ space: t,
178
+ coords: b(y(e), t),
179
+ alpha: e.alpha
180
+ };
181
+ }
182
+ var _ = (e) => Math.abs(e) <= .04045 ? e / 12.92 : Math.sign(e) * ((Math.abs(e) + .055) / 1.055) ** 2.4, v = (e) => Math.abs(e) <= .0031308 ? e * 12.92 : Math.sign(e) * (1.055 * Math.abs(e) ** (1 / 2.4) - .055);
183
+ function y({ space: e, coords: t }) {
184
+ if (e === "srgb-linear") return t;
185
+ if (e === "srgb") return t.map(_);
186
+ let [n, r, i] = e === "oklch" ? [
187
+ t[0],
188
+ t[1] * Math.cos(t[2] * Math.PI / 180),
189
+ t[1] * Math.sin(t[2] * Math.PI / 180)
190
+ ] : t, a = (n + .3963377774 * r + .2158037573 * i) ** 3, o = (n - .1055613458 * r - .0638541728 * i) ** 3, s = (n - .0894841775 * r - 1.291485548 * i) ** 3;
191
+ return [
192
+ 4.0767416621 * a - 3.3077115913 * o + .2309699292 * s,
193
+ -1.2684380046 * a + 2.6097574011 * o - .3413193965 * s,
194
+ -.0041960863 * a - .7034186147 * o + 1.707614701 * s
195
+ ];
196
+ }
197
+ function b([e, t, n], r) {
198
+ if (r === "srgb-linear") return [
199
+ e,
200
+ t,
201
+ n
202
+ ];
203
+ if (r === "srgb") return [
204
+ v(e),
205
+ v(t),
206
+ v(n)
207
+ ];
208
+ let i = Math.cbrt(.4122214708 * e + .5363325363 * t + .0514459929 * n), a = Math.cbrt(.2119034982 * e + .6806995451 * t + .1073969566 * n), o = Math.cbrt(.0883024619 * e + .2817188376 * t + .6299787005 * n), s = [
209
+ .2104542553 * i + .793617785 * a - .0040720468 * o,
210
+ 1.9779984951 * i - 2.428592205 * a + .4505937099 * o,
211
+ .0259040371 * i + .7827717662 * a - .808675766 * o
212
+ ];
213
+ if (r === "oklab") return s;
214
+ let c = Math.atan2(s[2], s[1]) * 180 / Math.PI;
215
+ return [
216
+ s[0],
217
+ Math.hypot(s[1], s[2]),
218
+ (c + 360) % 360
219
+ ];
220
+ }
221
+ //#endregion
222
+ export { _ as decode, t as resolveColor };
@@ -0,0 +1,18 @@
1
+ import { ColorRole } from "../tokens/roles.mjs";
2
+ import { Brand } from "../brands/brand.mjs";
3
+ import { Mode } from "./color.mjs";
4
+ //#region src/contrast/contrast.d.ts
5
+ export interface ContrastPair {
6
+ fg: ColorRole;
7
+ bg: ColorRole;
8
+ min: 4.5 | 3;
9
+ }
10
+ export interface ContrastFailure extends ContrastPair {
11
+ mode: Mode;
12
+ ratio: number;
13
+ }
14
+ export declare const contrastPairs: readonly ContrastPair[];
15
+ export declare function contrastRatio(fg: string, bg: string, mode?: Mode): number;
16
+ export declare function checkContrast(brand: Brand): ContrastFailure[];
17
+ //#endregion
18
+ export type { Mode };
@@ -0,0 +1,52 @@
1
+ import { decode as e, resolveColor as t } from "./color.mjs";
2
+ //#region src/contrast/contrast.ts
3
+ var n = [
4
+ "bg",
5
+ "bgMuted",
6
+ "bgRaised"
7
+ ], r = (e, t, n) => e.flatMap((e) => t.map((t) => ({
8
+ fg: e,
9
+ bg: t,
10
+ min: n
11
+ }))), i = [
12
+ ...r([
13
+ "fg",
14
+ "fgMuted",
15
+ "accent",
16
+ "danger"
17
+ ], n, 4.5),
18
+ ...r(["accentFg"], ["accent"], 4.5),
19
+ ...r(["dangerFg"], ["danger"], 4.5),
20
+ ...r(["borderStrong", "focus"], n, 3)
21
+ ], a = ["light", "dark"];
22
+ function o({ r: t, g: n, b: r }) {
23
+ return .2126 * e(t) + .7152 * e(n) + .0722 * e(r);
24
+ }
25
+ function s(e, n, r = "light") {
26
+ return c(t(e, r), t(n, r), n);
27
+ }
28
+ function c(e, t, n) {
29
+ if (t.alpha < 1) throw Error(`Contrast background must be opaque: ${n}`);
30
+ let r = (t, n) => t * e.alpha + n * (1 - e.alpha), [i, a] = [o({
31
+ r: r(e.r, t.r),
32
+ g: r(e.g, t.g),
33
+ b: r(e.b, t.b),
34
+ alpha: 1
35
+ }), o(t)].toSorted((e, t) => t - e);
36
+ return (i + .05) / (a + .05);
37
+ }
38
+ function l(e) {
39
+ return a.flatMap((n) => {
40
+ let r = /* @__PURE__ */ new Map(), a = (i) => r.get(i) ?? r.set(i, t(e.color[i], n)).get(i);
41
+ return i.flatMap((t) => {
42
+ let r = c(a(t.fg), a(t.bg), e.color[t.bg]);
43
+ return r < t.min ? [{
44
+ ...t,
45
+ mode: n,
46
+ ratio: r
47
+ }] : [];
48
+ });
49
+ });
50
+ }
51
+ //#endregion
52
+ export { l as checkContrast, i as contrastPairs, s as contrastRatio };
@@ -0,0 +1,33 @@
1
+ import { fills as e } from "../styles/button-fills.mjs";
2
+ import { contrastRatio as t } from "./contrast.mjs";
3
+ import { highlightFill as n, highlightText as r } from "../styles/highlight.mjs";
4
+ import { hoverFill as i } from "../styles/hover-tint.mjs";
5
+ //#region src/contrast/mixes.ts
6
+ var a = [{
7
+ name: "Menu highlight",
8
+ fill: n,
9
+ text: r,
10
+ min: 4.5
11
+ }, ...Object.entries(e).map(([e, { backgroundColor: t, color: n }]) => ({
12
+ name: `${e} Button hover`,
13
+ fill: (e) => i(e.fg, e[t]),
14
+ text: [n],
15
+ min: 4.5
16
+ }))];
17
+ function o(e) {
18
+ return ["light", "dark"].flatMap((n) => a.flatMap(({ name: r, fill: i, text: a, min: o }) => {
19
+ let s = i(e.color);
20
+ return a.flatMap((i) => {
21
+ let a = t(e.color[i], s, n);
22
+ return a < o ? [{
23
+ fg: i,
24
+ mix: r,
25
+ min: o,
26
+ mode: n,
27
+ ratio: a
28
+ }] : [];
29
+ });
30
+ }));
31
+ }
32
+ //#endregion
33
+ export { o as checkMixes, a as contrastMixes };
@@ -0,0 +1,113 @@
1
+ # AlertDialog
2
+
3
+ ## Purpose
4
+
5
+ Asks the user to confirm a consequential action before it runs: delete a project, discard unsaved changes, sign out every device. Built on Base UI's AlertDialog, which owns the behavior: `role="alertdialog"`, focus moves into the dialog and stays there, the page behind is inert, Esc closes it, and a click outside does not. It wears Dialog's panel at the `sm` width with a title, a description, Cancel and one confirm button, and Cancel takes focus on open.
6
+
7
+ ## When to use
8
+
9
+ - An action that destroys data or can't be undone, where a slip of the finger would cost the user.
10
+ - An action with a consequence the user may not expect (signing out everywhere, leaving a shared space).
11
+
12
+ ## When not to use
13
+
14
+ - A task with fields to fill or content to read: use `Dialog`.
15
+ - An action the user can undo: run it and offer Undo as a `Toast` action; a confirm on every click teaches people to click through.
16
+ - A status message or an error: use `Toast` or inline text; nothing needs confirming.
17
+
18
+ ## Rules
19
+
20
+ - It is one component, not parts: `title`, `description`, `confirmLabel` and `onConfirm` are required; `cancelLabel` defaults to "Cancel". Its only child is `AlertDialog.Trigger`, the same part as `Dialog.Trigger`.
21
+ - `title` is the question ("Delete project?"); `description` says what happens on confirm ("Its 12 invoices are deleted too. This can't be undone."). Both are announced when it opens.
22
+ - `confirmLabel` names the action as a verb ("Delete", "Sign out"), never "OK" or "Yes", so the button reads on its own.
23
+ - `tone="danger"` turns the confirm button `danger`, for an action that destroys or can't be undone. The default tone makes it `primary`.
24
+ - `onConfirm` runs once on the confirm button, then the dialog closes; a second click while it fades out does nothing. If it throws, the dialog stays open; a returned promise is not awaited. For an action that can fail, control it with `open` and `onOpenChange` and report the failure where the action started.
25
+ - Cancel comes first and takes focus, so Enter on open cancels. On a touch screen Base UI focuses the panel instead, so no button is pressed by accident.
26
+ - Without `AlertDialog.Trigger`, control it with `open` and `onOpenChange`; it then portals to `<body>`, as Dialog does.
27
+ - It is always modal and takes no `className`, `style` or style props: the panel is fixed so every confirm looks the same.
28
+ - The module has no hooks and no `"use client"`, but `onConfirm` is a function, so the component that renders it is a client component.
29
+
30
+ ## Do
31
+
32
+ ```tsx
33
+ <AlertDialog
34
+ title="Delete project?"
35
+ description="Its 12 invoices are deleted too. This can't be undone."
36
+ confirmLabel="Delete"
37
+ tone="danger"
38
+ onConfirm={deleteProject}
39
+ >
40
+ <AlertDialog.Trigger variant="secondary">Delete project</AlertDialog.Trigger>
41
+ </AlertDialog>
42
+ ```
43
+
44
+ ```tsx
45
+ // Opened from a menu item: no trigger, so control it.
46
+ const [open, setOpen] = useState(false);
47
+ <AlertDialog
48
+ open={open}
49
+ onOpenChange={setOpen}
50
+ title="Sign out of every device?"
51
+ description="You stay signed in here."
52
+ confirmLabel="Sign out"
53
+ onConfirm={signOutEverywhere}
54
+ />;
55
+ ```
56
+
57
+ ## Don't
58
+
59
+ ```tsx
60
+ // "OK" doesn't say what happens; name the action.
61
+ <AlertDialog title="Are you sure?" description="…" confirmLabel="OK" onConfirm={remove} />
62
+ ```
63
+
64
+ ```tsx
65
+ // A form in a confirm: use Dialog.
66
+ <AlertDialog
67
+ title="Rename project"
68
+ description={<Field>…</Field>}
69
+ confirmLabel="Save"
70
+ onConfirm={save}
71
+ />
72
+ ```
73
+
74
+ ## Accessibility
75
+
76
+ - The trigger has `aria-haspopup="dialog"` and `aria-expanded`. The popup is `role="alertdialog"`, labelled by the title and described by the description.
77
+ - Opening moves focus to Cancel; Tab and Shift+Tab cycle between the two buttons, and the page behind is inert. Esc or Cancel closes it, and focus returns to the trigger. A click outside does nothing.
78
+ - The danger confirm button is told apart by its label as well as its color.
79
+ - Under reduced motion the panel only fades.
80
+
81
+ ## Props
82
+
83
+ Generated from the TypeScript types.
84
+
85
+ ### AlertDialog
86
+
87
+ | Prop | Type | Required | Description |
88
+ | --- | --- | --- | --- |
89
+ | `cancelLabel` | `string` | no | |
90
+ | `children` | `ReactNode` | no | |
91
+ | `confirmLabel` | `string` | yes | |
92
+ | `defaultOpen` | `boolean` | no | Whether the dialog is initially open. To render a controlled dialog, use the `open` prop instead. |
93
+ | `description` | `string \| number \| bigint \| Iterable<ReactNode> \| Promise<AwaitedReactNode> \| ReactElement<unknown, string \| JSXElementConstructor<any>> \| ReactPortal` | yes | |
94
+ | `onConfirm` | `() => void` | yes | |
95
+ | `onOpenChange` | `((open: boolean, eventDetails: AlertDialogRootChangeEventDetails) => void)` | no | Event handler called when the alert dialog is opened or closed. |
96
+ | `onOpenChangeComplete` | `((open: boolean) => void)` | no | Event handler called after any animations complete when the dialog is opened or closed. |
97
+ | `open` | `boolean` | no | Whether the dialog is currently open. |
98
+ | `title` | `string \| number \| bigint \| Iterable<ReactNode> \| Promise<AwaitedReactNode> \| ReactElement<unknown, string \| JSXElementConstructor<any>> \| ReactPortal` | yes | |
99
+ | `tone` | `"danger" \| "default"` | no | |
100
+
101
+ ### AlertDialog.Trigger
102
+
103
+ | Prop | Type | Required | Description |
104
+ | --- | --- | --- | --- |
105
+ | `handle` | `DialogHandle<unknown>` | no | A handle to associate the trigger with a dialog. Can be created with the Dialog.createHandle() method. |
106
+ | `iconEnd` | `ComponentType` | no | |
107
+ | `iconStart` | `ComponentType` | no | |
108
+ | `id` | `string` | no | ID of the trigger. In addition to being forwarded to the rendered element, it is also used to specify the active trigger for the dialog in controlled mode (with the DialogRoot `triggerId` prop). |
109
+ | `payload` | `unknown` | no | A payload to pass to the dialog when it is opened. |
110
+ | `size` | `"lg" \| "med" \| "sm"` | no | |
111
+ | `variant` | `"primary" \| "secondary"` | no | |
112
+
113
+ Also accepts the style props (see `manifest.json` `styleProps`).