@-reddacted-/react-ui 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/dist/components/Accordion.d.ts +27 -0
  2. package/dist/components/Accordion.d.ts.map +1 -0
  3. package/dist/components/Accordion.js +35 -0
  4. package/dist/components/Badge.d.ts +15 -0
  5. package/dist/components/Badge.d.ts.map +1 -0
  6. package/dist/components/Badge.js +7 -0
  7. package/dist/components/Button.d.ts +15 -2
  8. package/dist/components/Button.d.ts.map +1 -1
  9. package/dist/components/Button.js +76 -44
  10. package/dist/components/Card.d.ts +21 -0
  11. package/dist/components/Card.d.ts.map +1 -0
  12. package/dist/components/Card.js +17 -0
  13. package/dist/components/ColorField.d.ts.map +1 -1
  14. package/dist/components/ColorField.js +1 -1
  15. package/dist/components/ConfirmDeleteButton.d.ts +4 -1
  16. package/dist/components/ConfirmDeleteButton.d.ts.map +1 -1
  17. package/dist/components/ConfirmDeleteButton.js +6 -7
  18. package/dist/components/Drawer.d.ts +33 -0
  19. package/dist/components/Drawer.d.ts.map +1 -0
  20. package/dist/components/Drawer.js +123 -0
  21. package/dist/components/DropdownMenu.d.ts +61 -0
  22. package/dist/components/DropdownMenu.d.ts.map +1 -0
  23. package/dist/components/DropdownMenu.js +302 -0
  24. package/dist/components/Modal.d.ts.map +1 -1
  25. package/dist/components/Modal.js +102 -134
  26. package/dist/components/NavBar.d.ts.map +1 -1
  27. package/dist/components/NavBar.js +4 -2
  28. package/dist/components/PageStatus.d.ts +12 -12
  29. package/dist/components/PageStatus.d.ts.map +1 -1
  30. package/dist/components/PageStatus.js +9 -29
  31. package/dist/components/Pagination.d.ts +44 -0
  32. package/dist/components/Pagination.d.ts.map +1 -0
  33. package/dist/components/Pagination.js +57 -0
  34. package/dist/components/Skeleton.d.ts +13 -0
  35. package/dist/components/Skeleton.d.ts.map +1 -0
  36. package/dist/components/Skeleton.js +15 -0
  37. package/dist/components/Spinner.d.ts +14 -0
  38. package/dist/components/Spinner.d.ts.map +1 -0
  39. package/dist/components/Spinner.js +14 -0
  40. package/dist/components/Stack.d.ts +13 -0
  41. package/dist/components/Stack.d.ts.map +1 -0
  42. package/dist/components/Stack.js +15 -0
  43. package/dist/components/Table.d.ts +54 -0
  44. package/dist/components/Table.d.ts.map +1 -0
  45. package/dist/components/Table.js +101 -0
  46. package/dist/components/Tabs.d.ts +34 -0
  47. package/dist/components/Tabs.d.ts.map +1 -0
  48. package/dist/components/Tabs.js +82 -0
  49. package/dist/components/Tag.d.ts +10 -0
  50. package/dist/components/Tag.d.ts.map +1 -0
  51. package/dist/components/Tag.js +7 -0
  52. package/dist/components/Tooltip.d.ts +22 -0
  53. package/dist/components/Tooltip.d.ts.map +1 -0
  54. package/dist/components/Tooltip.js +76 -0
  55. package/dist/components/drawerStore.d.ts +11 -0
  56. package/dist/components/drawerStore.d.ts.map +1 -0
  57. package/dist/components/drawerStore.js +40 -0
  58. package/dist/components/paginationItems.d.ts +18 -0
  59. package/dist/components/paginationItems.d.ts.map +1 -0
  60. package/dist/components/paginationItems.js +32 -0
  61. package/dist/index.d.ts +22 -6
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +16 -2
  64. package/dist/popup/PopupHost.d.ts +19 -3
  65. package/dist/popup/PopupHost.d.ts.map +1 -1
  66. package/dist/popup/PopupHost.js +65 -44
  67. package/dist/popup/PopupProvider.d.ts +19 -2
  68. package/dist/popup/PopupProvider.d.ts.map +1 -1
  69. package/dist/popup/PopupProvider.js +69 -17
  70. package/dist/popup/usePopup.d.ts +11 -4
  71. package/dist/popup/usePopup.d.ts.map +1 -1
  72. package/dist/style/accordionCss.d.ts +2 -0
  73. package/dist/style/accordionCss.d.ts.map +1 -0
  74. package/dist/style/accordionCss.js +101 -0
  75. package/dist/style/badgeCss.d.ts +5 -0
  76. package/dist/style/badgeCss.d.ts.map +1 -0
  77. package/dist/style/badgeCss.js +68 -0
  78. package/dist/style/breadcrumbCss.d.ts +2 -0
  79. package/dist/style/breadcrumbCss.d.ts.map +1 -0
  80. package/dist/style/breadcrumbCss.js +53 -0
  81. package/dist/style/cardCss.d.ts +2 -0
  82. package/dist/style/cardCss.d.ts.map +1 -0
  83. package/dist/style/cardCss.js +49 -0
  84. package/dist/style/inputCss.d.ts +2 -0
  85. package/dist/style/inputCss.d.ts.map +1 -0
  86. package/dist/style/inputCss.js +107 -0
  87. package/dist/style/loaderCss.d.ts +2 -0
  88. package/dist/style/loaderCss.d.ts.map +1 -0
  89. package/dist/style/loaderCss.js +39 -0
  90. package/dist/style/menuCss.d.ts +2 -0
  91. package/dist/style/menuCss.d.ts.map +1 -0
  92. package/dist/style/menuCss.js +71 -0
  93. package/dist/style/paginationCss.d.ts +2 -0
  94. package/dist/style/paginationCss.d.ts.map +1 -0
  95. package/dist/style/paginationCss.js +57 -0
  96. package/dist/style/resolveColor.d.ts +8 -0
  97. package/dist/style/resolveColor.d.ts.map +1 -0
  98. package/dist/style/resolveColor.js +13 -0
  99. package/dist/style/stackCss.d.ts +2 -0
  100. package/dist/style/stackCss.d.ts.map +1 -0
  101. package/dist/style/stackCss.js +21 -0
  102. package/dist/style/statusCss.d.ts +2 -0
  103. package/dist/style/statusCss.d.ts.map +1 -0
  104. package/dist/style/statusCss.js +38 -0
  105. package/dist/style/tableCss.d.ts +2 -0
  106. package/dist/style/tableCss.d.ts.map +1 -0
  107. package/dist/style/tableCss.js +92 -0
  108. package/dist/style/tabsCss.d.ts +2 -0
  109. package/dist/style/tabsCss.d.ts.map +1 -0
  110. package/dist/style/tabsCss.js +72 -0
  111. package/dist/style/toLength.d.ts +4 -0
  112. package/dist/style/toLength.d.ts.map +1 -0
  113. package/dist/style/toLength.js +3 -0
  114. package/dist/style/tooltipCss.d.ts +2 -0
  115. package/dist/style/tooltipCss.d.ts.map +1 -0
  116. package/dist/style/tooltipCss.js +44 -0
  117. package/dist/style/useStyle.d.ts +7 -0
  118. package/dist/style/useStyle.d.ts.map +1 -0
  119. package/dist/style/useStyle.js +16 -0
  120. package/dist/theme/ThemeProvider.d.ts.map +1 -1
  121. package/dist/theme/ThemeProvider.js +32 -0
  122. package/dist/theme/palette.d.ts.map +1 -1
  123. package/dist/theme/palette.js +0 -2
  124. package/dist/tooltip/attributeTooltips.d.ts +7 -0
  125. package/dist/tooltip/attributeTooltips.d.ts.map +1 -0
  126. package/dist/tooltip/attributeTooltips.js +76 -0
  127. package/dist/tooltip/tooltipEngine.d.ts +41 -0
  128. package/dist/tooltip/tooltipEngine.d.ts.map +1 -0
  129. package/dist/tooltip/tooltipEngine.js +128 -0
  130. package/dist/utils/childRef.d.ts +5 -0
  131. package/dist/utils/childRef.d.ts.map +1 -0
  132. package/dist/utils/childRef.js +14 -0
  133. package/dist/utils/isDev.d.ts +3 -0
  134. package/dist/utils/isDev.d.ts.map +1 -0
  135. package/dist/utils/isDev.js +4 -0
  136. package/package.json +5 -4
@@ -0,0 +1,21 @@
1
+ // Flex layout, usable as a bare class (`rui-stack`) or through the Stack component.
2
+ // Every selector is wrapped in :where() so it has zero specificity:
3
+ // any class or style set by the consuming project wins without !important.
4
+ export const stackCss = `
5
+ :where(.rui-stack) {
6
+ display: flex;
7
+ flex-direction: var(--rui-stack-direction, column);
8
+ flex-wrap: var(--rui-stack-wrap, nowrap);
9
+ gap: var(--rui-stack-gap, 0.75rem);
10
+ align-items: var(--rui-stack-align, stretch);
11
+ justify-content: var(--rui-stack-justify, flex-start);
12
+ }
13
+ /* Custom properties inherit: a nested stack must not take its parent's settings. */
14
+ :where(.rui-stack) > * {
15
+ --rui-stack-direction: initial;
16
+ --rui-stack-wrap: initial;
17
+ --rui-stack-gap: initial;
18
+ --rui-stack-align: initial;
19
+ --rui-stack-justify: initial;
20
+ }
21
+ `;
@@ -0,0 +1,2 @@
1
+ export declare const statusCss = "\n:where(.rui-status) {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--rui-status-gap, 0.75rem);\n padding: var(--rui-status-padding, 2rem);\n text-align: center;\n}\n:where(.rui-status-icon) {\n display: flex;\n color: var(--color-text-muted);\n font-size: var(--rui-status-icon-size, 2rem);\n}\n:where(.rui-status-title) {\n margin: 0;\n color: var(--color-text);\n font-size: 0.9375rem;\n font-weight: 600;\n}\n:where(.rui-status-description) {\n margin: 0;\n max-width: 40ch;\n color: var(--color-text-muted);\n font-size: 0.875rem;\n}\n:where(.rui-status-action) {\n display: flex;\n flex-wrap: wrap;\n justify-content: center;\n gap: 0.5rem;\n margin-top: 0.25rem;\n}\n";
2
+ //# sourceMappingURL=statusCss.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusCss.d.ts","sourceRoot":"","sources":["../../src/style/statusCss.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,SAAS,8tBAiCrB,CAAA"}
@@ -0,0 +1,38 @@
1
+ // Status block (loading, empty, error…): `rui-status` with optional `rui-status-icon`,
2
+ // `rui-status-title`, `rui-status-description` and `rui-status-action` children.
3
+ // Every selector is wrapped in :where() so it has zero specificity:
4
+ // any class or style set by the consuming project wins without !important.
5
+ export const statusCss = `
6
+ :where(.rui-status) {
7
+ display: flex;
8
+ flex-direction: column;
9
+ align-items: center;
10
+ gap: var(--rui-status-gap, 0.75rem);
11
+ padding: var(--rui-status-padding, 2rem);
12
+ text-align: center;
13
+ }
14
+ :where(.rui-status-icon) {
15
+ display: flex;
16
+ color: var(--color-text-muted);
17
+ font-size: var(--rui-status-icon-size, 2rem);
18
+ }
19
+ :where(.rui-status-title) {
20
+ margin: 0;
21
+ color: var(--color-text);
22
+ font-size: 0.9375rem;
23
+ font-weight: 600;
24
+ }
25
+ :where(.rui-status-description) {
26
+ margin: 0;
27
+ max-width: 40ch;
28
+ color: var(--color-text-muted);
29
+ font-size: 0.875rem;
30
+ }
31
+ :where(.rui-status-action) {
32
+ display: flex;
33
+ flex-wrap: wrap;
34
+ justify-content: center;
35
+ gap: 0.5rem;
36
+ margin-top: 0.25rem;
37
+ }
38
+ `;
@@ -0,0 +1,2 @@
1
+ export declare const tableCss = "\n:where(.rui-table-wrap) {\n overflow: auto;\n}\n:where(.rui-table) {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n color: var(--color-text);\n font-size: 0.875rem;\n}\n:where(.rui-table) :where(th, td) {\n padding: var(--rui-table-cell-padding, 0.625rem 0.875rem);\n text-align: left;\n vertical-align: middle;\n}\n:where(.rui-table) :where(th) {\n background-color: var(--rui-table-header-bg, var(--color-surface));\n color: var(--color-text-muted);\n font-weight: 600;\n white-space: nowrap;\n}\n\n:where(.rui-table:not([data-borders=\"none\"])) :where(th, td) {\n border-bottom: 1px solid var(--rui-table-border, var(--color-border));\n}\n:where(.rui-table:not([data-borders=\"none\"])) :where(tbody tr:last-child) > :where(td, th) {\n border-bottom: none;\n}\n:where(.rui-table[data-borders=\"grid\"]) {\n border: 1px solid var(--rui-table-border, var(--color-border));\n}\n:where(.rui-table[data-borders=\"grid\"]) :where(th, td) + :where(th, td) {\n border-left: 1px solid var(--rui-table-border, var(--color-border));\n}\n\n:where(.rui-table[data-sticky-header]) :where(thead th) {\n position: sticky;\n top: 0;\n z-index: 1;\n}\n\n:where(.rui-table[data-hover]) :where(tbody tr:hover) > :where(td, th) {\n background-color: color-mix(in srgb, var(--rui-table-accent, var(--color-primary)) 6%, transparent);\n}\n:where(.rui-table) :where(tbody tr[aria-selected]) {\n cursor: pointer;\n}\n:where(.rui-table) :where(tr[aria-selected=\"true\"]) > :where(td, th) {\n background-color: color-mix(in srgb, var(--rui-table-accent, var(--color-primary)) 12%, transparent);\n}\n:where(.rui-table) :where(tbody tr:focus-visible) {\n outline: 2px solid var(--rui-table-accent, var(--color-primary));\n outline-offset: -2px;\n}\n\n:where(.rui-table) :where(th[aria-sort=\"ascending\"], th[aria-sort=\"descending\"]) {\n color: var(--color-text);\n}\n:where(.rui-table) :where(th[aria-sort=\"ascending\"])::after {\n content: \" \u2191\";\n}\n:where(.rui-table) :where(th[aria-sort=\"descending\"])::after {\n content: \" \u2193\";\n}\n:where(.rui-table-sort) {\n padding: 0;\n border: none;\n background: none;\n color: inherit;\n font: inherit;\n text-align: inherit;\n cursor: pointer;\n}\n:where(.rui-table-sort:focus-visible) {\n outline: 2px solid var(--rui-table-accent, var(--color-primary));\n outline-offset: 2px;\n border-radius: 2px;\n}\n:where(.rui-table-empty) {\n padding: 2rem 1rem;\n color: var(--color-text-muted);\n text-align: center;\n}\n";
2
+ //# sourceMappingURL=tableCss.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tableCss.d.ts","sourceRoot":"","sources":["../../src/style/tableCss.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,QAAQ,09EAoFpB,CAAA"}
@@ -0,0 +1,92 @@
1
+ // Themed native table: `rui-table` on a <table>, inside an optional `rui-table-wrap`
2
+ // (horizontal scroll, and the scroll container a sticky header needs).
3
+ // Every selector is wrapped in :where() so it has zero specificity:
4
+ // any class or style set by the consuming project wins without !important.
5
+ const accent = "var(--rui-table-accent, var(--color-primary))";
6
+ const border = "1px solid var(--rui-table-border, var(--color-border))";
7
+ const cell = ":where(.rui-table) :where(th, td)";
8
+ export const tableCss = `
9
+ :where(.rui-table-wrap) {
10
+ overflow: auto;
11
+ }
12
+ :where(.rui-table) {
13
+ width: 100%;
14
+ border-collapse: separate;
15
+ border-spacing: 0;
16
+ color: var(--color-text);
17
+ font-size: 0.875rem;
18
+ }
19
+ ${cell} {
20
+ padding: var(--rui-table-cell-padding, 0.625rem 0.875rem);
21
+ text-align: left;
22
+ vertical-align: middle;
23
+ }
24
+ :where(.rui-table) :where(th) {
25
+ background-color: var(--rui-table-header-bg, var(--color-surface));
26
+ color: var(--color-text-muted);
27
+ font-weight: 600;
28
+ white-space: nowrap;
29
+ }
30
+
31
+ :where(.rui-table:not([data-borders="none"])) :where(th, td) {
32
+ border-bottom: ${border};
33
+ }
34
+ :where(.rui-table:not([data-borders="none"])) :where(tbody tr:last-child) > :where(td, th) {
35
+ border-bottom: none;
36
+ }
37
+ :where(.rui-table[data-borders="grid"]) {
38
+ border: ${border};
39
+ }
40
+ :where(.rui-table[data-borders="grid"]) :where(th, td) + :where(th, td) {
41
+ border-left: ${border};
42
+ }
43
+
44
+ :where(.rui-table[data-sticky-header]) :where(thead th) {
45
+ position: sticky;
46
+ top: 0;
47
+ z-index: 1;
48
+ }
49
+
50
+ :where(.rui-table[data-hover]) :where(tbody tr:hover) > :where(td, th) {
51
+ background-color: color-mix(in srgb, ${accent} 6%, transparent);
52
+ }
53
+ :where(.rui-table) :where(tbody tr[aria-selected]) {
54
+ cursor: pointer;
55
+ }
56
+ :where(.rui-table) :where(tr[aria-selected="true"]) > :where(td, th) {
57
+ background-color: color-mix(in srgb, ${accent} 12%, transparent);
58
+ }
59
+ :where(.rui-table) :where(tbody tr:focus-visible) {
60
+ outline: 2px solid ${accent};
61
+ outline-offset: -2px;
62
+ }
63
+
64
+ :where(.rui-table) :where(th[aria-sort="ascending"], th[aria-sort="descending"]) {
65
+ color: var(--color-text);
66
+ }
67
+ :where(.rui-table) :where(th[aria-sort="ascending"])::after {
68
+ content: " ↑";
69
+ }
70
+ :where(.rui-table) :where(th[aria-sort="descending"])::after {
71
+ content: " ↓";
72
+ }
73
+ :where(.rui-table-sort) {
74
+ padding: 0;
75
+ border: none;
76
+ background: none;
77
+ color: inherit;
78
+ font: inherit;
79
+ text-align: inherit;
80
+ cursor: pointer;
81
+ }
82
+ :where(.rui-table-sort:focus-visible) {
83
+ outline: 2px solid ${accent};
84
+ outline-offset: 2px;
85
+ border-radius: 2px;
86
+ }
87
+ :where(.rui-table-empty) {
88
+ padding: 2rem 1rem;
89
+ color: var(--color-text-muted);
90
+ text-align: center;
91
+ }
92
+ `;
@@ -0,0 +1,2 @@
1
+ export declare const tabsCss = "\n:where(.rui-tabs) {\n display: flex;\n gap: 0.25rem;\n}\n:where(.rui-tabs[aria-orientation=\"vertical\"]) {\n flex-direction: column;\n align-items: stretch;\n}\n:where(.rui-tabs) > :where(a, button, [role=\"tab\"]) {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 0.875rem;\n border: none;\n border-radius: 6px;\n background-color: transparent;\n color: var(--color-text-muted);\n font: inherit;\n font-size: 0.875rem;\n font-weight: 500;\n text-decoration: none;\n white-space: nowrap;\n cursor: pointer;\n}\n:where(.rui-tabs) > :where(a, button, [role=\"tab\"]):where(:hover) {\n color: var(--color-text);\n}\n:where(.rui-tabs) > :where(a, button, [role=\"tab\"]):where(:focus-visible) {\n outline: 2px solid var(--rui-tabs-color, var(--color-primary));\n outline-offset: -2px;\n}\n:where(.rui-tabs) > :where(a, button, [role=\"tab\"]):where(:disabled, [aria-disabled=\"true\"]) {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n:where(.rui-tabs:not([data-variant=\"pill\"]):not([aria-orientation=\"vertical\"])) {\n border-bottom: 1px solid var(--color-border);\n}\n:where(.rui-tabs:not([data-variant=\"pill\"]):not([aria-orientation=\"vertical\"])) > :where(a, button, [role=\"tab\"]) {\n margin-bottom: -1px;\n border-bottom: 2px solid transparent;\n border-radius: 6px 6px 0 0;\n}\n:where(.rui-tabs[aria-orientation=\"vertical\"]:not([data-variant=\"pill\"])) {\n border-right: 1px solid var(--color-border);\n}\n:where(.rui-tabs[aria-orientation=\"vertical\"]:not([data-variant=\"pill\"])) > :where(a, button, [role=\"tab\"]) {\n margin-right: -1px;\n border-right: 2px solid transparent;\n border-radius: 6px 0 0 6px;\n}\n:where(.rui-tabs:not([data-variant=\"pill\"])) > :where([aria-selected=\"true\"], [aria-current=\"page\"]) {\n border-color: var(--rui-tabs-color, var(--color-primary));\n color: var(--color-text);\n}\n\n:where(.rui-tabs[data-variant=\"pill\"]) > :where([aria-selected=\"true\"], [aria-current=\"page\"]) {\n background-color: color-mix(in srgb, var(--rui-tabs-color, var(--color-primary)) 12%, transparent);\n color: var(--rui-tabs-color, var(--color-primary));\n}\n";
2
+ //# sourceMappingURL=tabsCss.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabsCss.d.ts","sourceRoot":"","sources":["../../src/style/tabsCss.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,OAAO,0nEA8DnB,CAAA"}
@@ -0,0 +1,72 @@
1
+ // Tabs look, usable as a bare class (`rui-tabs` on the tab list, the project owning state
2
+ // and panels) or through the Tabs component. Tabs are the direct `a` / `button` /
3
+ // `[role=tab]` children; the active one has `aria-selected="true"` or `aria-current="page"`.
4
+ // Every selector is wrapped in :where() so it has zero specificity:
5
+ // any class or style set by the consuming project wins without !important.
6
+ const tab = `:where(a, button, [role="tab"])`;
7
+ const active = `:where([aria-selected="true"], [aria-current="page"])`;
8
+ const underline = `:where(.rui-tabs:not([data-variant="pill"]):not([aria-orientation="vertical"]))`;
9
+ const underlineVertical = `:where(.rui-tabs[aria-orientation="vertical"]:not([data-variant="pill"]))`;
10
+ export const tabsCss = `
11
+ :where(.rui-tabs) {
12
+ display: flex;
13
+ gap: 0.25rem;
14
+ }
15
+ :where(.rui-tabs[aria-orientation="vertical"]) {
16
+ flex-direction: column;
17
+ align-items: stretch;
18
+ }
19
+ :where(.rui-tabs) > ${tab} {
20
+ display: inline-flex;
21
+ align-items: center;
22
+ gap: 0.5rem;
23
+ padding: 0.5rem 0.875rem;
24
+ border: none;
25
+ border-radius: 6px;
26
+ background-color: transparent;
27
+ color: var(--color-text-muted);
28
+ font: inherit;
29
+ font-size: 0.875rem;
30
+ font-weight: 500;
31
+ text-decoration: none;
32
+ white-space: nowrap;
33
+ cursor: pointer;
34
+ }
35
+ :where(.rui-tabs) > ${tab}:where(:hover) {
36
+ color: var(--color-text);
37
+ }
38
+ :where(.rui-tabs) > ${tab}:where(:focus-visible) {
39
+ outline: 2px solid var(--rui-tabs-color, var(--color-primary));
40
+ outline-offset: -2px;
41
+ }
42
+ :where(.rui-tabs) > ${tab}:where(:disabled, [aria-disabled="true"]) {
43
+ opacity: 0.4;
44
+ cursor: not-allowed;
45
+ }
46
+
47
+ ${underline} {
48
+ border-bottom: 1px solid var(--color-border);
49
+ }
50
+ ${underline} > ${tab} {
51
+ margin-bottom: -1px;
52
+ border-bottom: 2px solid transparent;
53
+ border-radius: 6px 6px 0 0;
54
+ }
55
+ ${underlineVertical} {
56
+ border-right: 1px solid var(--color-border);
57
+ }
58
+ ${underlineVertical} > ${tab} {
59
+ margin-right: -1px;
60
+ border-right: 2px solid transparent;
61
+ border-radius: 6px 0 0 6px;
62
+ }
63
+ :where(.rui-tabs:not([data-variant="pill"])) > ${active} {
64
+ border-color: var(--rui-tabs-color, var(--color-primary));
65
+ color: var(--color-text);
66
+ }
67
+
68
+ :where(.rui-tabs[data-variant="pill"]) > ${active} {
69
+ background-color: color-mix(in srgb, var(--rui-tabs-color, var(--color-primary)) 12%, transparent);
70
+ color: var(--rui-tabs-color, var(--color-primary));
71
+ }
72
+ `;
@@ -0,0 +1,4 @@
1
+ /** Numbers are pixels; strings are any CSS length, kept as is. */
2
+ export declare function toLength(value: string | number): string;
3
+ export declare function toLength(value: string | number | undefined): string | undefined;
4
+ //# sourceMappingURL=toLength.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toLength.d.ts","sourceRoot":"","sources":["../../src/style/toLength.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;AACxD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAA"}
@@ -0,0 +1,3 @@
1
+ export function toLength(value) {
2
+ return typeof value === "number" ? `${value}px` : value;
3
+ }
@@ -0,0 +1,2 @@
1
+ export declare const tooltipCss = "\n:where(.rui-tooltip) {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 2100;\n box-sizing: border-box;\n width: max-content;\n max-width: var(--rui-tooltip-max-width, 240px);\n padding: 0.375rem 0.625rem;\n border-radius: 6px;\n background-color: var(--rui-tooltip-bg, var(--color-text));\n color: var(--rui-tooltip-color, var(--color-bg));\n font-size: 0.8125rem;\n line-height: 1.4;\n overflow-wrap: break-word;\n pointer-events: none;\n animation: rui-tooltip-in 120ms ease-out;\n}\n/* Not positioned yet: hidden rather than shown at the corner or at its previous anchor. */\n:where(.rui-tooltip:not([data-placement])) {\n visibility: hidden;\n animation: none;\n}\n:where(.rui-tooltip-arrow) {\n position: absolute;\n width: 8px;\n height: 8px;\n background-color: inherit;\n transform: rotate(45deg);\n}\n@media (prefers-reduced-motion: reduce) {\n :where(.rui-tooltip) {\n animation: none;\n }\n}\n@keyframes rui-tooltip-in {\n from { opacity: 0; }\n}\n";
2
+ //# sourceMappingURL=tooltipCss.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tooltipCss.d.ts","sourceRoot":"","sources":["../../src/style/tooltipCss.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,s+BAuCtB,CAAA"}
@@ -0,0 +1,44 @@
1
+ // Tooltip bubble, shared by the Tooltip component and the `data-rui-tooltip` attribute.
2
+ // Every selector is wrapped in :where() so it has zero specificity:
3
+ // any class or style set by the consuming project wins without !important.
4
+ // Above the overlay stack (from 1000) and the toasts (2000): a tooltip can come from a modal.
5
+ export const tooltipCss = `
6
+ :where(.rui-tooltip) {
7
+ position: fixed;
8
+ top: 0;
9
+ left: 0;
10
+ z-index: 2100;
11
+ box-sizing: border-box;
12
+ width: max-content;
13
+ max-width: var(--rui-tooltip-max-width, 240px);
14
+ padding: 0.375rem 0.625rem;
15
+ border-radius: 6px;
16
+ background-color: var(--rui-tooltip-bg, var(--color-text));
17
+ color: var(--rui-tooltip-color, var(--color-bg));
18
+ font-size: 0.8125rem;
19
+ line-height: 1.4;
20
+ overflow-wrap: break-word;
21
+ pointer-events: none;
22
+ animation: rui-tooltip-in 120ms ease-out;
23
+ }
24
+ /* Not positioned yet: hidden rather than shown at the corner or at its previous anchor. */
25
+ :where(.rui-tooltip:not([data-placement])) {
26
+ visibility: hidden;
27
+ animation: none;
28
+ }
29
+ :where(.rui-tooltip-arrow) {
30
+ position: absolute;
31
+ width: 8px;
32
+ height: 8px;
33
+ background-color: inherit;
34
+ transform: rotate(45deg);
35
+ }
36
+ @media (prefers-reduced-motion: reduce) {
37
+ :where(.rui-tooltip) {
38
+ animation: none;
39
+ }
40
+ }
41
+ @keyframes rui-tooltip-in {
42
+ from { opacity: 0; }
43
+ }
44
+ `;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Injects `css` once into document.head under `data-rui="<id>"`.
3
+ * Runs before layout (no flash) and is never removed: the CSS is static and light,
4
+ * keeping it avoids flicker when the component remounts.
5
+ */
6
+ export declare function useStyle(id: string, css: string): void;
7
+ //# sourceMappingURL=useStyle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStyle.d.ts","sourceRoot":"","sources":["../../src/style/useStyle.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAQtD"}
@@ -0,0 +1,16 @@
1
+ import { useInsertionEffect } from "react";
2
+ /**
3
+ * Injects `css` once into document.head under `data-rui="<id>"`.
4
+ * Runs before layout (no flash) and is never removed: the CSS is static and light,
5
+ * keeping it avoids flicker when the component remounts.
6
+ */
7
+ export function useStyle(id, css) {
8
+ useInsertionEffect(() => {
9
+ if (document.head.querySelector(`style[data-rui="${id}"]`))
10
+ return;
11
+ const style = document.createElement("style");
12
+ style.dataset.rui = id;
13
+ style.textContent = css;
14
+ document.head.appendChild(style);
15
+ }, [id, css]);
16
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/theme/ThemeProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAI9D,KAAK,iBAAiB,GAAG;IACvB,MAAM,EAAE,eAAe,EAAE,CAAA;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,aAAa,EAAE,WAAW,CAAA;IAC1B,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,UAAU,CAAA;IACjB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5B,CAAA;AAID,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,SAAS,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAOD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,MAAM,EACN,KAAK,EACL,WAA4B,EAC5B,YAA4B,GAC7B,EAAE,kBAAkB,+BA6DpB;AAED,wBAAgB,QAAQ,IAAI,iBAAiB,CAI5C"}
1
+ {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/theme/ThemeProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAmB9D,KAAK,iBAAiB,GAAG;IACvB,MAAM,EAAE,eAAe,EAAE,CAAA;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,aAAa,EAAE,WAAW,CAAA;IAC1B,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,UAAU,CAAA;IACjB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5B,CAAA;AAID,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,SAAS,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAOD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,MAAM,EACN,KAAK,EACL,WAA4B,EAC5B,YAA4B,GAC7B,EAAE,kBAAkB,+BAgFpB;AAED,wBAAgB,QAAQ,IAAI,iBAAiB,CAI5C"}
@@ -2,6 +2,21 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
3
3
  import { defaultPalette } from "./palette.js";
4
4
  import { createHttpThemeStore, createLocalThemeStore } from "./store.js";
5
+ import { useStyle } from "../style/useStyle.js";
6
+ import { inputCss } from "../style/inputCss.js";
7
+ import { loaderCss } from "../style/loaderCss.js";
8
+ import { cardCss } from "../style/cardCss.js";
9
+ import { stackCss } from "../style/stackCss.js";
10
+ import { badgeCss } from "../style/badgeCss.js";
11
+ import { tabsCss } from "../style/tabsCss.js";
12
+ import { tooltipCss } from "../style/tooltipCss.js";
13
+ import { menuCss } from "../style/menuCss.js";
14
+ import { tableCss } from "../style/tableCss.js";
15
+ import { statusCss } from "../style/statusCss.js";
16
+ import { paginationCss } from "../style/paginationCss.js";
17
+ import { breadcrumbCss } from "../style/breadcrumbCss.js";
18
+ import { accordionCss } from "../style/accordionCss.js";
19
+ import { installAttributeTooltips } from "../tooltip/attributeTooltips.js";
5
20
  const SELECTION_KEY = "theme-id";
6
21
  const ThemeContext = createContext(null);
7
22
  function readSelection(key) {
@@ -10,6 +25,23 @@ function readSelection(key) {
10
25
  return localStorage.getItem(key);
11
26
  }
12
27
  export function ThemeProvider({ children, apiUrl, store, basePalette = defaultPalette, selectionKey = SELECTION_KEY, }) {
28
+ // Class-only styles (`rui-*` put by the project on its own elements) live here:
29
+ // the provider is always mounted.
30
+ useStyle("input", inputCss);
31
+ useStyle("loader", loaderCss);
32
+ useStyle("card", cardCss);
33
+ useStyle("stack", stackCss);
34
+ useStyle("badge", badgeCss);
35
+ useStyle("tabs", tabsCss);
36
+ useStyle("tooltip", tooltipCss);
37
+ useStyle("menu", menuCss);
38
+ useStyle("table", tableCss);
39
+ useStyle("status", statusCss);
40
+ useStyle("pagination", paginationCss);
41
+ useStyle("breadcrumb", breadcrumbCss);
42
+ useStyle("accordion", accordionCss);
43
+ // `data-rui-tooltip` on any element: one set of delegated listeners for the page.
44
+ useEffect(() => installAttributeTooltips(), []);
13
45
  const resolvedStore = useMemo(() => store ?? (apiUrl ? createHttpThemeStore(apiUrl) : createLocalThemeStore()), [store, apiUrl]);
14
46
  const [themes, setThemes] = useState([]);
15
47
  const [defaultId, setDefaultId] = useState(null);
@@ -1 +1 @@
1
- {"version":3,"file":"palette.d.ts","sourceRoot":"","sources":["../../src/theme/palette.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAK7C,eAAO,MAAM,cAAc,EAAE,WAW5B,CAAA"}
1
+ {"version":3,"file":"palette.d.ts","sourceRoot":"","sources":["../../src/theme/palette.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAK7C,eAAO,MAAM,cAAc,EAAE,WAS5B,CAAA"}
@@ -10,6 +10,4 @@ export const defaultPalette = {
10
10
  "--color-primary": "#6366f1",
11
11
  "--color-primary-hover": "#4f46e5",
12
12
  "--color-on-primary": "#ffffff",
13
- "--color-danger": "#dc2626",
14
- "--color-danger-soft": "#fee2e2",
15
13
  };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Page-wide delegated listeners: any element with `data-rui-tooltip="text"` (optionally
3
+ * `data-rui-tooltip-placement`) gets a tooltip, including elements added later.
4
+ * Returns the uninstall function.
5
+ */
6
+ export declare function installAttributeTooltips(): () => void;
7
+ //# sourceMappingURL=attributeTooltips.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attributeTooltips.d.ts","sourceRoot":"","sources":["../../src/tooltip/attributeTooltips.ts"],"names":[],"mappings":"AAiBA;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,IAAI,CAuDrD"}
@@ -0,0 +1,76 @@
1
+ import { TooltipEngine } from "./tooltipEngine.js";
2
+ const SELECTOR = "[data-rui-tooltip]";
3
+ const DELAY = 300;
4
+ function tooltipTarget(target) {
5
+ return target instanceof Element ? target.closest(SELECTOR) : null;
6
+ }
7
+ function toggleDescribedBy(el, id, add) {
8
+ const ids = (el.getAttribute("aria-describedby") ?? "").split(/\s+/).filter(token => token && token !== id);
9
+ if (add)
10
+ ids.push(id);
11
+ if (ids.length > 0)
12
+ el.setAttribute("aria-describedby", ids.join(" "));
13
+ else
14
+ el.removeAttribute("aria-describedby");
15
+ }
16
+ /**
17
+ * Page-wide delegated listeners: any element with `data-rui-tooltip="text"` (optionally
18
+ * `data-rui-tooltip-placement`) gets a tooltip, including elements added later.
19
+ * Returns the uninstall function.
20
+ */
21
+ export function installAttributeTooltips() {
22
+ const engine = new TooltipEngine((open, anchor) => toggleDescribedBy(anchor, engine.id, open));
23
+ const prepare = (el) => {
24
+ engine.content.textContent = el.dataset.ruiTooltip ?? "";
25
+ engine.setLook({ placement: el.dataset.ruiTooltipPlacement ?? "top" });
26
+ };
27
+ const onPointerOver = (event) => {
28
+ if (event.pointerType === "touch")
29
+ return;
30
+ const el = tooltipTarget(event.target);
31
+ if (!el || el === engine.anchor)
32
+ return;
33
+ engine.scheduleShow(el, DELAY, () => prepare(el));
34
+ };
35
+ const onPointerOut = (event) => {
36
+ if (event.pointerType === "touch")
37
+ return;
38
+ const el = tooltipTarget(event.target);
39
+ if (el && !el.contains(event.relatedTarget))
40
+ engine.hide();
41
+ };
42
+ const onFocusIn = (event) => {
43
+ const el = tooltipTarget(event.target);
44
+ if (!el)
45
+ return;
46
+ prepare(el);
47
+ engine.show(el);
48
+ };
49
+ const onFocusOut = (event) => {
50
+ const el = tooltipTarget(event.target);
51
+ if (el && !el.contains(event.relatedTarget))
52
+ engine.hide();
53
+ };
54
+ const onPointerDown = (event) => {
55
+ if (event.pointerType !== "touch")
56
+ return;
57
+ const el = tooltipTarget(event.target);
58
+ if (!el)
59
+ return;
60
+ prepare(el);
61
+ engine.showForTouch(el);
62
+ };
63
+ document.addEventListener("pointerover", onPointerOver);
64
+ document.addEventListener("pointerout", onPointerOut);
65
+ document.addEventListener("focusin", onFocusIn);
66
+ document.addEventListener("focusout", onFocusOut);
67
+ document.addEventListener("pointerdown", onPointerDown);
68
+ return () => {
69
+ document.removeEventListener("pointerover", onPointerOver);
70
+ document.removeEventListener("pointerout", onPointerOut);
71
+ document.removeEventListener("focusin", onFocusIn);
72
+ document.removeEventListener("focusout", onFocusOut);
73
+ document.removeEventListener("pointerdown", onPointerDown);
74
+ engine.hide();
75
+ };
76
+ }
@@ -0,0 +1,41 @@
1
+ import type { Placement } from "@floating-ui/dom";
2
+ export type TooltipPlacement = Placement;
3
+ export type TooltipLook = {
4
+ placement?: TooltipPlacement;
5
+ /** Background and arrow. `"--color-x"` reads the theme variable; anything else is a raw CSS color. */
6
+ color?: string;
7
+ textColor?: string;
8
+ maxWidth?: string | number;
9
+ };
10
+ /**
11
+ * One tooltip bubble (a detached DOM element, appended to the body while open) with its
12
+ * timers, positioning and dismissal. Shared by the Tooltip component and the
13
+ * `data-rui-tooltip` attribute mode so both behave the same.
14
+ */
15
+ export declare class TooltipEngine {
16
+ private readonly onOpenChange?;
17
+ readonly id: string;
18
+ readonly bubble: HTMLDivElement;
19
+ /** Where the content goes: text in attribute mode, a portal for the component. */
20
+ readonly content: HTMLDivElement;
21
+ private readonly arrowEl;
22
+ private placement;
23
+ private anchorEl;
24
+ private showTimer;
25
+ private hideTimer;
26
+ private stopAutoUpdate;
27
+ constructor(onOpenChange?: ((open: boolean, anchor: HTMLElement) => void) | undefined);
28
+ get anchor(): HTMLElement | null;
29
+ setLook({ placement, color, textColor, maxWidth }: TooltipLook): void;
30
+ /** Opens on `anchor` after `delay` ms (right away when 0). */
31
+ scheduleShow(anchor: HTMLElement, delay: number, beforeShow?: () => void): void;
32
+ /** Opens on a touch, closing by itself shortly after. */
33
+ showForTouch(anchor: HTMLElement): void;
34
+ show(anchor: HTMLElement): void;
35
+ hide(): void;
36
+ private clearTimers;
37
+ private readonly onKeyDown;
38
+ private readonly onPointerDown;
39
+ private position;
40
+ }
41
+ //# sourceMappingURL=tooltipEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tooltipEngine.d.ts","sourceRoot":"","sources":["../../src/tooltip/tooltipEngine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAIjD,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAA;AAExC,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,CAAC,EAAE,gBAAgB,CAAA;IAC5B,sGAAsG;IACtG,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAC3B,CAAA;AAOD;;;;GAIG;AACH,qBAAa,aAAa;IAYZ,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAX1C,QAAQ,CAAC,EAAE,SAA4B;IACvC,QAAQ,CAAC,MAAM,iBAAgC;IAC/C,kFAAkF;IAClF,QAAQ,CAAC,OAAO,iBAAgC;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,SAAS,CAA2C;IAC5D,OAAO,CAAC,SAAS,CAA2C;IAC5D,OAAO,CAAC,cAAc,CAA0B;gBAEnB,YAAY,CAAC,GAAE,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,KAAK,IAAI,aAAA;IAUxF,IAAI,MAAM,IAAI,WAAW,GAAG,IAAI,CAE/B;IAED,OAAO,CAAC,EAAE,SAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,WAAW,GAAG,IAAI;IAS7E,8DAA8D;IAC9D,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI;IAW/E,yDAAyD;IACzD,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAKvC,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAa/B,IAAI,IAAI,IAAI;IAeZ,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAIzB;IAGD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAE7B;YAEa,QAAQ;CAyBvB"}