@sarunyu/system-one 4.9.34 → 4.9.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +17 -5
- package/DESIGN.md +1 -0
- package/dist/index.cjs +214 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +214 -7
- package/dist/index.js.map +1 -1
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/style.css +1 -1
- package/llms.txt +13 -2
- package/package.json +4 -1
package/AGENTS.md
CHANGED
|
@@ -117,14 +117,26 @@ utilities (`p-6`, `gap-4`, `max-w-*`, etc.) win over host-written ones.
|
|
|
117
117
|
|
|
118
118
|
## Dark mode
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
**Global dark mode** — add `.dark` to `<html>`. All tokens adapt automatically.
|
|
121
|
+
|
|
122
|
+
**Section-level dark mode** — add `data-theme="dark"` to any container with a
|
|
123
|
+
dark background. All child components automatically switch to dark tokens.
|
|
124
|
+
Never use `class="dark"` for sections — that resets the entire page theme.
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
// ✅ section on a dark background
|
|
128
|
+
<div data-theme="dark" className="bg-bg-brand-primary rounded-2xl p-8">
|
|
129
|
+
<Button>ติดต่อ Online Service</Button>
|
|
130
|
+
<p className="text-text-default-primary">สีปรับอัตโนมัติ</p>
|
|
131
|
+
</div>
|
|
132
|
+
```
|
|
121
133
|
|
|
122
134
|
## Theming
|
|
123
135
|
|
|
124
136
|
Override CSS custom properties after the stylesheet import.
|
|
125
|
-
**Both `:root` (light) and `.dark` (dark) must be overridden
|
|
126
|
-
the library hard-codes dark-mode colors in its `.dark` block,
|
|
127
|
-
override leaves dark mode unchanged.
|
|
137
|
+
**Both `:root` (light) and `.dark, [data-theme="dark"]` (dark) must be overridden
|
|
138
|
+
separately** — the library hard-codes dark-mode colors in its `.dark` block,
|
|
139
|
+
so a `:root`-only override leaves dark mode unchanged.
|
|
128
140
|
|
|
129
141
|
```css
|
|
130
142
|
:root {
|
|
@@ -134,7 +146,7 @@ override leaves dark mode unchanged.
|
|
|
134
146
|
--font-sans: "Inter", sans-serif;
|
|
135
147
|
}
|
|
136
148
|
|
|
137
|
-
.dark {
|
|
149
|
+
.dark, [data-theme="dark"] {
|
|
138
150
|
--primary-action: #a78bfa;
|
|
139
151
|
--primary-action-hover: #c4b5fd;
|
|
140
152
|
--primary-action-active: #8b5cf6;
|
package/DESIGN.md
CHANGED
|
@@ -236,6 +236,7 @@ Use sparingly. Corporate UIs prefer border separation over heavy elevation.
|
|
|
236
236
|
| Do | Don't |
|
|
237
237
|
|---|---|
|
|
238
238
|
| Use `bg-background`, `bg-card` for surfaces | Hard-code `#ffffff` or `bg-white` |
|
|
239
|
+
| Use `data-theme="dark"` on dark-background sections | Use `class="dark"` on a section (resets the whole page) |
|
|
239
240
|
| Use `text-foreground` for body text | Use `text-gray-900` or `text-black` |
|
|
240
241
|
| Use `border-border` for dividers | Use `border-gray-200` |
|
|
241
242
|
| Use `rounded` (4px) by default | Use `rounded-xl` or `rounded-2xl` on data elements |
|
package/dist/index.cjs
CHANGED
|
@@ -3068,7 +3068,7 @@ function RemovableTag({
|
|
|
3068
3068
|
react.X,
|
|
3069
3069
|
{
|
|
3070
3070
|
size: 12,
|
|
3071
|
-
weight: "
|
|
3071
|
+
weight: "regular",
|
|
3072
3072
|
color: iconColor,
|
|
3073
3073
|
className: "shrink-0"
|
|
3074
3074
|
}
|
|
@@ -3607,7 +3607,7 @@ const DropdownMultiple = React.forwardRef(
|
|
|
3607
3607
|
react.Check,
|
|
3608
3608
|
{
|
|
3609
3609
|
size: 12,
|
|
3610
|
-
weight: "
|
|
3610
|
+
weight: "regular",
|
|
3611
3611
|
className: "text-primary-action"
|
|
3612
3612
|
}
|
|
3613
3613
|
)
|
|
@@ -4250,7 +4250,7 @@ function ToastCloseButton({
|
|
|
4250
4250
|
colorClass
|
|
4251
4251
|
),
|
|
4252
4252
|
onClick: onClose,
|
|
4253
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 12, weight: "
|
|
4253
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 12, weight: "regular" })
|
|
4254
4254
|
}
|
|
4255
4255
|
);
|
|
4256
4256
|
}
|
|
@@ -4441,7 +4441,7 @@ const OptionList = React.forwardRef(
|
|
|
4441
4441
|
react.Check,
|
|
4442
4442
|
{
|
|
4443
4443
|
size: 16,
|
|
4444
|
-
weight: "
|
|
4444
|
+
weight: "regular",
|
|
4445
4445
|
className: "text-primary-action"
|
|
4446
4446
|
}
|
|
4447
4447
|
) })
|
|
@@ -4811,7 +4811,7 @@ const Tag = React.forwardRef(function Tag2({
|
|
|
4811
4811
|
className: cn(
|
|
4812
4812
|
"inline-flex items-center justify-center rounded-[2px] transition-colors",
|
|
4813
4813
|
s.closeButton,
|
|
4814
|
-
!isDisabled && "cursor-pointer hover:bg-black/10"
|
|
4814
|
+
!isDisabled && "cursor-pointer hover:bg-black/10 dark:hover:bg-white/10"
|
|
4815
4815
|
),
|
|
4816
4816
|
children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { disabled: isDisabled, className: s.closeIcon })
|
|
4817
4817
|
}
|
|
@@ -4889,7 +4889,7 @@ function StickyShadowEdge({ direction }) {
|
|
|
4889
4889
|
"aria-hidden": "true",
|
|
4890
4890
|
className: "pointer-events-none absolute inset-y-0 left-[-10px] w-2.5",
|
|
4891
4891
|
style: {
|
|
4892
|
-
background: "linear-gradient(90deg, rgba(
|
|
4892
|
+
background: "linear-gradient(90deg, rgba(var(--scroll-shadow-rgb),0.00) 0%, rgba(var(--scroll-shadow-rgb),0.03) 55%, rgba(var(--scroll-shadow-rgb),0.08) 100%)"
|
|
4893
4893
|
}
|
|
4894
4894
|
}
|
|
4895
4895
|
);
|
|
@@ -4900,7 +4900,7 @@ function StickyShadowEdge({ direction }) {
|
|
|
4900
4900
|
"aria-hidden": "true",
|
|
4901
4901
|
className: "pointer-events-none absolute inset-y-0 right-[-10px] w-2.5",
|
|
4902
4902
|
style: {
|
|
4903
|
-
background: "linear-gradient(90deg, rgba(
|
|
4903
|
+
background: "linear-gradient(90deg, rgba(var(--scroll-shadow-rgb),0.08) 0%, rgba(var(--scroll-shadow-rgb),0.03) 45%, rgba(var(--scroll-shadow-rgb),0.00) 100%)"
|
|
4904
4904
|
}
|
|
4905
4905
|
}
|
|
4906
4906
|
);
|
|
@@ -6158,6 +6158,207 @@ function Breadcrumb({ items, className }) {
|
|
|
6158
6158
|
] }, index2);
|
|
6159
6159
|
}) });
|
|
6160
6160
|
}
|
|
6161
|
+
function PaginationBanner({
|
|
6162
|
+
count: count2,
|
|
6163
|
+
activeIndex,
|
|
6164
|
+
onIndexChange,
|
|
6165
|
+
className
|
|
6166
|
+
}) {
|
|
6167
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6168
|
+
"div",
|
|
6169
|
+
{
|
|
6170
|
+
className: cn("flex items-center gap-1", className),
|
|
6171
|
+
role: "tablist",
|
|
6172
|
+
"aria-label": "Slide indicators",
|
|
6173
|
+
children: Array.from({ length: count2 }, (_, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
6174
|
+
"button",
|
|
6175
|
+
{
|
|
6176
|
+
type: "button",
|
|
6177
|
+
role: "tab",
|
|
6178
|
+
"aria-selected": i === activeIndex,
|
|
6179
|
+
"aria-label": `Slide ${i + 1}`,
|
|
6180
|
+
onClick: () => onIndexChange == null ? void 0 : onIndexChange(i),
|
|
6181
|
+
className: cn(
|
|
6182
|
+
"h-1.5 rounded-[12px] transition-all duration-200",
|
|
6183
|
+
i === activeIndex ? "w-8 bg-bg-brand" : "w-1.5 bg-black/10 dark:bg-white/10 hover:bg-black/20 dark:hover:bg-white/20"
|
|
6184
|
+
)
|
|
6185
|
+
},
|
|
6186
|
+
i
|
|
6187
|
+
))
|
|
6188
|
+
}
|
|
6189
|
+
);
|
|
6190
|
+
}
|
|
6191
|
+
function PaginationCarousel({
|
|
6192
|
+
progress,
|
|
6193
|
+
trackWidth = 40,
|
|
6194
|
+
className
|
|
6195
|
+
}) {
|
|
6196
|
+
const clamped = Math.min(1, Math.max(0, progress));
|
|
6197
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6198
|
+
"div",
|
|
6199
|
+
{
|
|
6200
|
+
className: cn("flex items-center", className),
|
|
6201
|
+
role: "progressbar",
|
|
6202
|
+
"aria-valuenow": Math.round(clamped * 100),
|
|
6203
|
+
"aria-valuemin": 0,
|
|
6204
|
+
"aria-valuemax": 100,
|
|
6205
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6206
|
+
"div",
|
|
6207
|
+
{
|
|
6208
|
+
className: "relative h-1.5 overflow-hidden rounded-[48px] bg-black/10 dark:bg-white/10",
|
|
6209
|
+
style: { width: trackWidth },
|
|
6210
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6211
|
+
"div",
|
|
6212
|
+
{
|
|
6213
|
+
className: "absolute left-0 top-0 h-full rounded-[12px] bg-bg-brand transition-all duration-200",
|
|
6214
|
+
style: { width: Math.round(clamped * trackWidth) }
|
|
6215
|
+
}
|
|
6216
|
+
)
|
|
6217
|
+
}
|
|
6218
|
+
)
|
|
6219
|
+
}
|
|
6220
|
+
);
|
|
6221
|
+
}
|
|
6222
|
+
function buildPageItems(total) {
|
|
6223
|
+
if (total <= 5) return Array.from({ length: total }, (_, i) => i + 1);
|
|
6224
|
+
return [1, 2, 3, "...", total];
|
|
6225
|
+
}
|
|
6226
|
+
function buildHiddenPages(total) {
|
|
6227
|
+
if (total <= 5) return [];
|
|
6228
|
+
return Array.from({ length: total - 4 }, (_, i) => i + 4);
|
|
6229
|
+
}
|
|
6230
|
+
function Pagination({
|
|
6231
|
+
totalPages,
|
|
6232
|
+
currentPage,
|
|
6233
|
+
onPageChange,
|
|
6234
|
+
className
|
|
6235
|
+
}) {
|
|
6236
|
+
const [dropdownOpen, setDropdownOpen] = React.useState(false);
|
|
6237
|
+
const containerRef = React.useRef(null);
|
|
6238
|
+
const ellipsisRef = React.useRef(null);
|
|
6239
|
+
React.useEffect(() => {
|
|
6240
|
+
if (!dropdownOpen) return;
|
|
6241
|
+
function handleOutside(e) {
|
|
6242
|
+
var _a;
|
|
6243
|
+
if (!((_a = containerRef.current) == null ? void 0 : _a.contains(e.target))) {
|
|
6244
|
+
setDropdownOpen(false);
|
|
6245
|
+
}
|
|
6246
|
+
}
|
|
6247
|
+
document.addEventListener("mousedown", handleOutside);
|
|
6248
|
+
return () => document.removeEventListener("mousedown", handleOutside);
|
|
6249
|
+
}, [dropdownOpen]);
|
|
6250
|
+
const pageItems = buildPageItems(totalPages);
|
|
6251
|
+
const hiddenPages = buildHiddenPages(totalPages);
|
|
6252
|
+
const goTo = (page) => {
|
|
6253
|
+
if (page >= 1 && page <= totalPages && page !== currentPage) {
|
|
6254
|
+
onPageChange == null ? void 0 : onPageChange(page);
|
|
6255
|
+
setDropdownOpen(false);
|
|
6256
|
+
}
|
|
6257
|
+
};
|
|
6258
|
+
const cell = "flex h-8 w-[39px] shrink-0 items-center justify-center text-sm leading-5 transition-colors select-none";
|
|
6259
|
+
const divider = "border-l border-border";
|
|
6260
|
+
const ellipsisLeft = ellipsisRef.current ? ellipsisRef.current.offsetLeft + ellipsisRef.current.offsetWidth / 2 : void 0;
|
|
6261
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: cn("relative inline-flex w-fit", className), children: [
|
|
6262
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6263
|
+
"nav",
|
|
6264
|
+
{
|
|
6265
|
+
"aria-label": "Pagination",
|
|
6266
|
+
className: "inline-flex w-fit overflow-hidden rounded-lg border border-border",
|
|
6267
|
+
children: [
|
|
6268
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6269
|
+
"button",
|
|
6270
|
+
{
|
|
6271
|
+
type: "button",
|
|
6272
|
+
"aria-label": "Previous page",
|
|
6273
|
+
disabled: currentPage <= 1,
|
|
6274
|
+
onClick: () => goTo(currentPage - 1),
|
|
6275
|
+
className: cn(
|
|
6276
|
+
cell,
|
|
6277
|
+
"bg-bg-default text-icon-default hover:bg-bg-default-hover disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer"
|
|
6278
|
+
),
|
|
6279
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(react.CaretLeft, { size: 16, weight: "regular" })
|
|
6280
|
+
}
|
|
6281
|
+
),
|
|
6282
|
+
pageItems.map(
|
|
6283
|
+
(item, idx) => item === "..." ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6284
|
+
"button",
|
|
6285
|
+
{
|
|
6286
|
+
ref: ellipsisRef,
|
|
6287
|
+
type: "button",
|
|
6288
|
+
"aria-label": "More pages",
|
|
6289
|
+
"aria-expanded": dropdownOpen,
|
|
6290
|
+
"aria-haspopup": "listbox",
|
|
6291
|
+
onClick: () => setDropdownOpen((v) => !v),
|
|
6292
|
+
className: cn(
|
|
6293
|
+
cell,
|
|
6294
|
+
divider,
|
|
6295
|
+
"bg-bg-default text-text-default cursor-pointer hover:bg-bg-default-hover"
|
|
6296
|
+
),
|
|
6297
|
+
children: "..."
|
|
6298
|
+
},
|
|
6299
|
+
`ellipsis-${idx}`
|
|
6300
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
6301
|
+
"button",
|
|
6302
|
+
{
|
|
6303
|
+
type: "button",
|
|
6304
|
+
"aria-label": `Page ${item}`,
|
|
6305
|
+
"aria-current": item === currentPage ? "page" : void 0,
|
|
6306
|
+
onClick: () => goTo(item),
|
|
6307
|
+
className: cn(
|
|
6308
|
+
cell,
|
|
6309
|
+
divider,
|
|
6310
|
+
"cursor-pointer",
|
|
6311
|
+
item === currentPage ? "bg-bg-brand font-bold text-text-default-white" : "bg-bg-default font-normal text-text-default hover:bg-bg-default-hover"
|
|
6312
|
+
),
|
|
6313
|
+
children: item
|
|
6314
|
+
},
|
|
6315
|
+
item
|
|
6316
|
+
)
|
|
6317
|
+
),
|
|
6318
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6319
|
+
"button",
|
|
6320
|
+
{
|
|
6321
|
+
type: "button",
|
|
6322
|
+
"aria-label": "Next page",
|
|
6323
|
+
disabled: currentPage >= totalPages,
|
|
6324
|
+
onClick: () => goTo(currentPage + 1),
|
|
6325
|
+
className: cn(
|
|
6326
|
+
cell,
|
|
6327
|
+
divider,
|
|
6328
|
+
"bg-bg-default text-icon-default hover:bg-bg-default-hover disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer"
|
|
6329
|
+
),
|
|
6330
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(react.CaretRight, { size: 16, weight: "regular" })
|
|
6331
|
+
}
|
|
6332
|
+
)
|
|
6333
|
+
]
|
|
6334
|
+
}
|
|
6335
|
+
),
|
|
6336
|
+
dropdownOpen && hiddenPages.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6337
|
+
"div",
|
|
6338
|
+
{
|
|
6339
|
+
role: "listbox",
|
|
6340
|
+
"aria-label": "Select page",
|
|
6341
|
+
className: "absolute bottom-full mb-1 z-50 flex w-[39px] flex-col overflow-y-auto rounded-lg border border-border bg-bg-default shadow-md [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
6342
|
+
style: { left: ellipsisLeft, transform: "translateX(-50%)", maxHeight: 160 },
|
|
6343
|
+
children: hiddenPages.map((page) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
6344
|
+
"button",
|
|
6345
|
+
{
|
|
6346
|
+
type: "button",
|
|
6347
|
+
role: "option",
|
|
6348
|
+
"aria-selected": page === currentPage,
|
|
6349
|
+
onClick: () => goTo(page),
|
|
6350
|
+
className: cn(
|
|
6351
|
+
"flex h-8 w-full shrink-0 cursor-pointer items-center justify-center text-sm leading-5 transition-colors select-none",
|
|
6352
|
+
page === currentPage ? "bg-bg-brand font-bold text-text-default-white" : "bg-bg-default font-normal text-text-default hover:bg-bg-default-hover"
|
|
6353
|
+
),
|
|
6354
|
+
children: page
|
|
6355
|
+
},
|
|
6356
|
+
page
|
|
6357
|
+
))
|
|
6358
|
+
}
|
|
6359
|
+
)
|
|
6360
|
+
] });
|
|
6361
|
+
}
|
|
6161
6362
|
function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
|
|
6162
6363
|
return function handleEvent(event) {
|
|
6163
6364
|
originalEventHandler == null ? void 0 : originalEventHandler(event);
|
|
@@ -9585,6 +9786,9 @@ const index = {
|
|
|
9585
9786
|
Avatar,
|
|
9586
9787
|
AvatarStack,
|
|
9587
9788
|
Breadcrumb,
|
|
9789
|
+
Pagination,
|
|
9790
|
+
PaginationBanner,
|
|
9791
|
+
PaginationCarousel,
|
|
9588
9792
|
Tooltip,
|
|
9589
9793
|
Popover,
|
|
9590
9794
|
cn,
|
|
@@ -9607,6 +9811,9 @@ exports.Input = Input;
|
|
|
9607
9811
|
exports.Modal = Modal;
|
|
9608
9812
|
exports.Notification = Notification;
|
|
9609
9813
|
exports.OptionList = OptionList;
|
|
9814
|
+
exports.Pagination = Pagination;
|
|
9815
|
+
exports.PaginationBanner = PaginationBanner;
|
|
9816
|
+
exports.PaginationCarousel = PaginationCarousel;
|
|
9610
9817
|
exports.Popover = Popover;
|
|
9611
9818
|
exports.Radio = Radio;
|
|
9612
9819
|
exports.SearchInput = SearchInput;
|