@wipco/sdui 0.2.0 → 0.3.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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +27 -0
  3. package/dist/chunk-4SU2KYPU.js +59 -0
  4. package/dist/chunk-56KKWLNI.js +186 -0
  5. package/dist/chunk-7Y4J7EOK.js +115 -0
  6. package/dist/chunk-APCXOCAO.js +110 -0
  7. package/dist/chunk-AROOQ5W6.js +119 -0
  8. package/dist/chunk-DGPRX4MU.js +251 -0
  9. package/dist/chunk-IL2KS4WS.js +25 -0
  10. package/dist/chunk-KADFN76X.js +541 -0
  11. package/dist/chunk-KBHI3IUR.js +40 -0
  12. package/dist/chunk-LZJTKVMO.js +767 -0
  13. package/dist/chunk-MOIU7MUA.js +282 -0
  14. package/dist/chunk-MSAV4J4I.js +77 -0
  15. package/dist/chunk-OOHHW4K4.js +159 -0
  16. package/dist/chunk-Q6SBH63R.js +190 -0
  17. package/dist/chunk-QZQDHSMD.js +78 -0
  18. package/dist/chunk-RH7ESUE6.js +309 -0
  19. package/dist/chunk-SEBPBUZR.js +260 -0
  20. package/dist/chunk-USKRM22W.js +39 -0
  21. package/dist/chunk-WNYWTFGW.js +61 -0
  22. package/dist/chunk-WVRCIVAD.js +72 -0
  23. package/dist/chunk-YJMD6MOE.js +404 -0
  24. package/dist/chunk-ZNITJ4KK.js +433 -0
  25. package/dist/chunk-ZQR3ULVH.js +193 -0
  26. package/dist/{chunk-QJHD6HVQ.js → chunk-ZUCI34QY.js} +106 -390
  27. package/dist/index.d.ts +306 -53
  28. package/dist/index.js +276 -720
  29. package/dist/meta.d.ts +8 -0
  30. package/dist/meta.js +147 -8
  31. package/dist/rich.js +3 -2
  32. package/dist/styles.css +246 -0
  33. package/dist/widgets/AutocompleteField.d.ts +96 -0
  34. package/dist/widgets/AutocompleteField.js +3 -0
  35. package/dist/widgets/ColumnBoard.d.ts +47 -0
  36. package/dist/widgets/ColumnBoard.js +2 -0
  37. package/dist/widgets/DiffView.d.ts +30 -0
  38. package/dist/widgets/DiffView.js +2 -0
  39. package/dist/widgets/Disclosure.d.ts +20 -0
  40. package/dist/widgets/Disclosure.js +2 -0
  41. package/dist/widgets/EventCalendar.d.ts +59 -0
  42. package/dist/widgets/EventCalendar.js +2 -0
  43. package/dist/widgets/ImageLightbox.d.ts +25 -0
  44. package/dist/widgets/ImageLightbox.js +2 -0
  45. package/dist/widgets/InlineEdit.d.ts +23 -0
  46. package/dist/widgets/InlineEdit.js +2 -0
  47. package/dist/widgets/JsonField.d.ts +24 -0
  48. package/dist/widgets/JsonField.js +2 -0
  49. package/dist/widgets/LiveClock.d.ts +21 -0
  50. package/dist/widgets/LiveClock.js +1 -0
  51. package/dist/widgets/OrgChart.d.ts +32 -0
  52. package/dist/widgets/OrgChart.js +2 -0
  53. package/dist/widgets/PeriodFilter.d.ts +48 -0
  54. package/dist/widgets/PeriodFilter.js +2 -0
  55. package/dist/widgets/PrintSheet.d.ts +23 -0
  56. package/dist/widgets/PrintSheet.js +2 -0
  57. package/dist/widgets/SearchableMultiPicker.d.ts +29 -0
  58. package/dist/widgets/SearchableMultiPicker.js +3 -0
  59. package/dist/widgets/SecureScreen.d.ts +25 -0
  60. package/dist/widgets/SecureScreen.js +2 -0
  61. package/dist/widgets/StackedMeter.d.ts +26 -0
  62. package/dist/widgets/StackedMeter.js +1 -0
  63. package/dist/widgets/Strip.d.ts +20 -0
  64. package/dist/widgets/Strip.js +1 -0
  65. package/dist/widgets/SummaryTable.d.ts +31 -0
  66. package/dist/widgets/SummaryTable.js +1 -0
  67. package/dist/widgets/TagMultiSelect.d.ts +25 -0
  68. package/dist/widgets/TagMultiSelect.js +2 -0
  69. package/dist/widgets/Timeline.d.ts +30 -0
  70. package/dist/widgets/Timeline.js +3 -0
  71. package/dist/widgets/TreePicker.d.ts +21 -0
  72. package/dist/widgets/TreePicker.js +3 -0
  73. package/dist/widgets/TreeView.d.ts +26 -0
  74. package/dist/widgets/TreeView.js +2 -0
  75. package/dist/widgets/index.d.ts +76 -0
  76. package/dist/widgets/index.js +69 -0
  77. package/package.json +93 -3
@@ -1,4 +1,4 @@
1
- import React, { useState, useRef, useMemo, useCallback, useEffect, useLayoutEffect } from 'react';
1
+ import React from 'react';
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
 
4
4
  // src/components.tsx
@@ -1172,403 +1172,119 @@ function Dialog({ title, subtitle, icon, tone = "brand", size = "md", footer, on
1172
1172
  footer ? /* @__PURE__ */ jsx("div", { className: "wp-dialog__foot", children: footer }) : null
1173
1173
  ] }) });
1174
1174
  }
1175
- function HoistedStyle({ id, css }) {
1176
- return /* @__PURE__ */ jsx("style", { href: id, precedence: "medium", children: css });
1177
- }
1178
- var YMD_RE = /^\d{4}-\d{2}-\d{2}$/;
1179
- function parseYmd(value) {
1180
- if (typeof value !== "string" || !YMD_RE.test(value)) return void 0;
1181
- const y = Number(value.slice(0, 4));
1182
- const m = Number(value.slice(5, 7));
1183
- const d = Number(value.slice(8, 10));
1184
- const date = new Date(y, m - 1, d, 12, 0, 0, 0);
1185
- if (date.getFullYear() !== y || date.getMonth() !== m - 1 || date.getDate() !== d) return void 0;
1186
- return date;
1187
- }
1188
- function formatYmd(date) {
1189
- const y = String(date.getFullYear()).padStart(4, "0");
1190
- const m = String(date.getMonth() + 1).padStart(2, "0");
1191
- const d = String(date.getDate()).padStart(2, "0");
1192
- return `${y}-${m}-${d}`;
1193
- }
1194
- function addDays(date, days) {
1195
- const next = new Date(date);
1196
- next.setDate(next.getDate() + days);
1197
- return next;
1198
- }
1199
- function addMonths(date, months) {
1200
- const next = new Date(date.getFullYear(), date.getMonth() + months, 1, 12, 0, 0, 0);
1201
- const lastDay = new Date(next.getFullYear(), next.getMonth() + 1, 0).getDate();
1202
- next.setDate(Math.min(date.getDate(), lastDay));
1203
- return next;
1204
- }
1205
- function clampDate(date, min, max) {
1206
- if (min && date.getTime() < min.getTime()) return min;
1207
- if (max && date.getTime() > max.getTime()) return max;
1208
- return date;
1209
- }
1210
- function monthIndex(date) {
1211
- return date.getFullYear() * 12 + date.getMonth();
1212
- }
1213
- function monthStart(index) {
1214
- return new Date(Math.floor(index / 12), index % 12, 1, 12, 0, 0, 0);
1215
- }
1216
- function isSameDay(a, b) {
1217
- return a !== void 0 && b !== void 0 && formatYmd(a) === formatYmd(b);
1218
- }
1219
- var WEEKDAYS_KO = ["\uC77C", "\uC6D4", "\uD654", "\uC218", "\uBAA9", "\uAE08", "\uD1A0"];
1220
- var WEEKS_PER_MONTH = 6;
1221
- function buildMonthCells(index, min, max) {
1222
- const first = monthStart(index);
1223
- const gridStart = addDays(first, -first.getDay());
1224
- const weeks = [];
1225
- for (let w = 0; w < WEEKS_PER_MONTH; w += 1) {
1226
- const row = [];
1227
- for (let d = 0; d < 7; d += 1) {
1228
- const date = addDays(gridStart, w * 7 + d);
1229
- row.push({
1230
- date,
1231
- ymd: formatYmd(date),
1232
- outside: monthIndex(date) !== index,
1233
- disabled: min !== void 0 && date.getTime() < min.getTime() || max !== void 0 && date.getTime() > max.getTime()
1234
- });
1235
- }
1236
- weeks.push(row);
1237
- }
1238
- return weeks;
1175
+ function SegmentedControl({ items = [], value, onChange, size = "md", className = "", ...rest }) {
1176
+ const classes = ["wp-seg"];
1177
+ if (size === "lg") classes.push("wp-seg--lg");
1178
+ if (className) classes.push(className);
1179
+ return /* @__PURE__ */ jsx("div", { className: classes.join(" "), role: "tablist", ...rest, children: items.map((it) => /* @__PURE__ */ jsxs(
1180
+ "button",
1181
+ {
1182
+ type: "button",
1183
+ role: "tab",
1184
+ className: "wp-seg__item",
1185
+ "aria-selected": value === it.value,
1186
+ onClick: onChange ? () => onChange(it.value) : void 0,
1187
+ children: [
1188
+ it.icon ? /* @__PURE__ */ jsx(Icon, { name: it.icon, size: 14 }) : null,
1189
+ it.label
1190
+ ]
1191
+ },
1192
+ it.value
1193
+ )) });
1239
1194
  }
1240
- function Calendar({
1241
- monthCount,
1242
- minDate,
1243
- maxDate,
1244
- dayState,
1245
- onPick,
1246
- focusDate,
1247
- onFocusDateChange
1248
- }) {
1249
- const focusIdx = monthIndex(focusDate);
1250
- const [viewIdx, setViewIdx] = useState(focusIdx);
1251
- const gridRef = useRef(null);
1252
- const focusYmd = formatYmd(focusDate);
1253
- const visibleIdx = focusIdx < viewIdx ? focusIdx : focusIdx > viewIdx + monthCount - 1 ? focusIdx - monthCount + 1 : viewIdx;
1254
- if (visibleIdx !== viewIdx) setViewIdx(visibleIdx);
1255
- useLayoutEffect(() => {
1256
- gridRef.current?.querySelector('[tabindex="0"]')?.focus();
1257
- }, [focusYmd]);
1258
- const todayYmd = formatYmd(/* @__PURE__ */ new Date());
1259
- const minIdx = minDate ? monthIndex(minDate) : -Infinity;
1260
- const maxIdx = maxDate ? monthIndex(maxDate) : Infinity;
1261
- const prevDisabled = visibleIdx <= minIdx;
1262
- const nextDisabled = visibleIdx + monthCount - 1 >= maxIdx;
1263
- const moveFocus = (next) => {
1264
- onFocusDateChange(clampDate(next, minDate, maxDate));
1265
- };
1266
- const handleKeyDown = (event) => {
1267
- const deltaDays = event.key === "ArrowLeft" ? -1 : event.key === "ArrowRight" ? 1 : event.key === "ArrowUp" ? -7 : event.key === "ArrowDown" ? 7 : 0;
1268
- if (deltaDays !== 0) {
1269
- event.preventDefault();
1270
- moveFocus(addDays(focusDate, deltaDays));
1271
- return;
1272
- }
1273
- if (event.key === "Home" || event.key === "End") {
1274
- event.preventDefault();
1275
- const offset = event.key === "Home" ? -focusDate.getDay() : 6 - focusDate.getDay();
1276
- moveFocus(addDays(focusDate, offset));
1277
- return;
1278
- }
1279
- if (event.key === "PageUp" || event.key === "PageDown") {
1280
- event.preventDefault();
1281
- moveFocus(addMonths(focusDate, event.key === "PageUp" ? -1 : 1));
1282
- }
1283
- };
1284
- return /* @__PURE__ */ jsx("div", { className: "wp-dp", children: /* @__PURE__ */ jsxs("div", { className: "wp-dp__months", ref: gridRef, onKeyDown: handleKeyDown, children: [
1285
- /* @__PURE__ */ jsxs("div", { className: "wp-dp__nav", children: [
1286
- /* @__PURE__ */ jsx(
1287
- "button",
1288
- {
1289
- type: "button",
1290
- className: "wp-dp__navbtn",
1291
- "aria-label": "\uC774\uC804 \uB2EC",
1292
- "aria-disabled": prevDisabled || void 0,
1293
- disabled: prevDisabled,
1294
- onClick: () => setViewIdx(visibleIdx - 1),
1295
- children: /* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: 16 })
1296
- }
1297
- ),
1298
- /* @__PURE__ */ jsx(
1299
- "button",
1300
- {
1301
- type: "button",
1302
- className: "wp-dp__navbtn",
1303
- "aria-label": "\uB2E4\uC74C \uB2EC",
1304
- "aria-disabled": nextDisabled || void 0,
1305
- disabled: nextDisabled,
1306
- onClick: () => setViewIdx(visibleIdx + 1),
1307
- children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 16 })
1308
- }
1309
- )
1310
- ] }),
1311
- Array.from({ length: monthCount }, (_, offset) => {
1312
- const idx = visibleIdx + offset;
1313
- const first = monthStart(idx);
1314
- const weeks = buildMonthCells(idx, minDate, maxDate);
1315
- const caption = `${first.getFullYear()}\uB144 ${first.getMonth() + 1}\uC6D4`;
1316
- return /* @__PURE__ */ jsxs("div", { className: "wp-dp__month", children: [
1317
- /* @__PURE__ */ jsx("div", { className: "wp-dp__caption", children: /* @__PURE__ */ jsx("span", { className: "wp-dp__caption-label", children: caption }) }),
1318
- /* @__PURE__ */ jsxs("table", { className: "wp-dp__grid", role: "grid", "aria-label": caption, children: [
1319
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { className: "wp-dp__weekdays", children: WEEKDAYS_KO.map((name) => /* @__PURE__ */ jsx("th", { scope: "col", className: "wp-dp__weekday", abbr: name, children: name }, name)) }) }),
1320
- /* @__PURE__ */ jsx("tbody", { className: "wp-dp__weeks", children: weeks.map((week, w) => /* @__PURE__ */ jsx("tr", { className: "wp-dp__week", children: week.map((cell) => {
1321
- const state = cell.disabled ? {} : dayState(cell.date);
1322
- const classes = ["wp-dp__day"];
1323
- if (cell.outside) classes.push("wp-dp__day--outside");
1324
- if (cell.disabled) classes.push("wp-dp__day--disabled");
1325
- if (cell.ymd === todayYmd) classes.push("wp-dp__day--today");
1326
- if (state.selected) classes.push("wp-dp__day--selected");
1327
- if (state.rangeStart) classes.push("wp-dp__day--range-start");
1328
- if (state.rangeMiddle) classes.push("wp-dp__day--range-middle");
1329
- if (state.rangeEnd) classes.push("wp-dp__day--range-end");
1330
- return /* @__PURE__ */ jsx("td", { className: classes.join(" "), children: /* @__PURE__ */ jsx(
1331
- "button",
1332
- {
1333
- type: "button",
1334
- className: "wp-dp__day-btn",
1335
- "data-ymd": cell.ymd,
1336
- tabIndex: cell.ymd === focusYmd && !cell.outside ? 0 : -1,
1337
- disabled: cell.disabled,
1338
- "aria-selected": state.selected || state.rangeStart || state.rangeEnd || void 0,
1339
- "aria-label": cell.ymd,
1340
- onClick: () => {
1341
- onFocusDateChange(cell.date);
1342
- onPick(cell.date);
1343
- },
1344
- children: cell.date.getDate()
1345
- }
1346
- ) }, cell.ymd);
1347
- }) }, w)) })
1348
- ] })
1349
- ] }, idx);
1350
- })
1351
- ] }) });
1195
+ function Avatar({ name = "", src, shape = "hex", size = "md", tone = "brand", className = "", ...rest }) {
1196
+ const classes = ["wp-avatar", "wp-avatar--" + shape];
1197
+ if (size !== "md") classes.push("wp-avatar--" + size);
1198
+ if (tone !== "brand") classes.push("wp-avatar--" + tone);
1199
+ if (className) classes.push(className);
1200
+ const initials = name.trim().slice(0, 2).toUpperCase();
1201
+ return /* @__PURE__ */ jsx("span", { className: classes.join(" "), title: name || void 0, ...rest, children: src ? /* @__PURE__ */ jsx("img", { src, alt: name }) : initials });
1352
1202
  }
1353
- function useDismiss(open, hostRef, onDismiss) {
1354
- useEffect(() => {
1355
- if (!open) return;
1356
- const handlePointerDown = (event) => {
1357
- if (event.target instanceof Node && hostRef.current?.contains(event.target)) return;
1358
- onDismiss("outside");
1359
- };
1360
- const handleKeyDown = (event) => {
1361
- if (event.key === "Escape") onDismiss("escape");
1362
- };
1363
- document.addEventListener("pointerdown", handlePointerDown);
1364
- document.addEventListener("keydown", handleKeyDown);
1365
- return () => {
1366
- document.removeEventListener("pointerdown", handlePointerDown);
1367
- document.removeEventListener("keydown", handleKeyDown);
1368
- };
1369
- }, [open, hostRef, onDismiss]);
1203
+ function Breadcrumb({ items = [], className = "", ...rest }) {
1204
+ return /* @__PURE__ */ jsx("nav", { className: ("wp-crumbs " + className).trim(), "aria-label": "\uC704\uCE58", ...rest, children: items.map((it, i) => {
1205
+ const last = i === items.length - 1;
1206
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
1207
+ last ? /* @__PURE__ */ jsx("span", { className: "wp-crumbs__current", "aria-current": "page", children: it.label }) : /* @__PURE__ */ jsxs("a", { className: "wp-crumbs__item", href: it.href || "#", onClick: (e) => {
1208
+ if (!it.href) e.preventDefault();
1209
+ if (it.onClick) it.onClick();
1210
+ }, children: [
1211
+ it.icon ? /* @__PURE__ */ jsx(Icon, { name: it.icon, size: 13 }) : null,
1212
+ it.label
1213
+ ] }),
1214
+ last ? null : /* @__PURE__ */ jsx("span", { className: "wp-crumbs__sep", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 12 }) })
1215
+ ] }, `${it.label}${i}`);
1216
+ }) });
1370
1217
  }
1371
- function triggerClassName(size, invalid) {
1372
- const classes = ["wp-input", "wp-dp-trigger"];
1373
- if (size !== "md") classes.push(`wp-input--${size}`);
1374
- if (invalid) classes.push("wp-input--invalid");
1375
- return classes.join(" ");
1218
+ function Radio({ label, description, disabled = false, className = "", ...rest }) {
1219
+ const classes = ["wp-check"];
1220
+ if (disabled) classes.push("wp-check--disabled");
1221
+ if (className) classes.push(className);
1222
+ return /* @__PURE__ */ jsxs("label", { className: classes.join(" "), children: [
1223
+ /* @__PURE__ */ jsx("input", { type: "radio", disabled, ...rest }),
1224
+ /* @__PURE__ */ jsx("span", { className: "wp-check__box wp-check__box--radio" }),
1225
+ label || description ? /* @__PURE__ */ jsxs("span", { className: "wp-check__text", children: [
1226
+ /* @__PURE__ */ jsx("span", { children: label }),
1227
+ description ? /* @__PURE__ */ jsx("span", { className: "wp-check__desc", children: description }) : null
1228
+ ] }) : null
1229
+ ] });
1376
1230
  }
1377
- function DatePicker({
1378
- value,
1379
- onChange,
1380
- min,
1381
- max,
1382
- placeholder,
1383
- invalid = false,
1384
- disabled = false,
1385
- size = "md"
1386
- }) {
1387
- const [open, setOpen] = useState(false);
1388
- const [innerValue, setInnerValue] = useState("");
1389
- const hostRef = useRef(null);
1390
- const triggerRef = useRef(null);
1391
- const isControlled = value !== void 0;
1392
- const currentValue = isControlled ? value : innerValue;
1393
- const selectedDate = useMemo(() => parseYmd(currentValue), [currentValue]);
1394
- const minDate = useMemo(() => parseYmd(min), [min]);
1395
- const maxDate = useMemo(() => parseYmd(max), [max]);
1396
- const [focusDate, setFocusDate] = useState(() => selectedDate ?? clampDate(/* @__PURE__ */ new Date(), minDate, maxDate));
1397
- const dismiss = useCallback((reason) => {
1398
- setOpen(false);
1399
- if (reason === "escape") triggerRef.current?.focus();
1400
- }, []);
1401
- useDismiss(open, hostRef, dismiss);
1402
- const openCalendar = () => {
1403
- setFocusDate(selectedDate ?? clampDate(/* @__PURE__ */ new Date(), minDate, maxDate));
1404
- setOpen(true);
1405
- };
1406
- const isInvalid = Boolean(invalid);
1407
- return /* @__PURE__ */ jsxs("div", { ref: hostRef, className: "wp-dp-host", children: [
1408
- /* @__PURE__ */ jsx(HoistedStyle, { id: "wp-datepicker", css: DP_CSS }),
1409
- /* @__PURE__ */ jsxs(
1410
- "button",
1231
+ function SidebarNav({ sections = [], value, onSelect, collapsed = false, light = false, className = "", ...rest }) {
1232
+ const classes = ["wp-nav"];
1233
+ if (collapsed) classes.push("wp-nav--collapsed");
1234
+ if (light) classes.push("wp-nav--light");
1235
+ if (className) classes.push(className);
1236
+ return /* @__PURE__ */ jsx("nav", { className: classes.join(" "), ...rest, children: sections.map((s, si) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
1237
+ s.label ? /* @__PURE__ */ jsx("div", { className: "wp-nav__section", children: s.label }) : null,
1238
+ (s.items || []).map((it) => /* @__PURE__ */ jsxs(
1239
+ "a",
1411
1240
  {
1412
- ref: triggerRef,
1413
- type: "button",
1414
- className: triggerClassName(size, isInvalid),
1415
- "aria-invalid": isInvalid || void 0,
1416
- "aria-haspopup": "dialog",
1417
- "aria-expanded": open,
1418
- disabled,
1419
- onClick: () => open ? setOpen(false) : openCalendar(),
1241
+ href: it.href || "#",
1242
+ className: "wp-nav__item",
1243
+ "aria-current": value === it.value ? "page" : void 0,
1244
+ title: collapsed ? it.label : void 0,
1245
+ onClick: (e) => {
1246
+ if (!it.href) e.preventDefault();
1247
+ if (onSelect) onSelect(it.value);
1248
+ },
1420
1249
  children: [
1421
- /* @__PURE__ */ jsx("span", { className: "wp-dp-trigger__icon", children: /* @__PURE__ */ jsx(Icon, { name: "calendar", size: size === "lg" ? 16 : 15 }) }),
1422
- currentValue ? /* @__PURE__ */ jsx("span", { className: "wp-dp-trigger__value", children: selectedDate ? formatYmd(selectedDate) : currentValue }) : /* @__PURE__ */ jsx("span", { className: "wp-dp-trigger__value wp-dp-trigger__value--placeholder", children: placeholder ?? "\uB0A0\uC9DC \uC120\uD0DD" })
1250
+ it.icon ? /* @__PURE__ */ jsx("span", { className: "wp-nav__icon", children: /* @__PURE__ */ jsx(Icon, { name: it.icon, size: 17 }) }) : null,
1251
+ /* @__PURE__ */ jsx("span", { className: "wp-nav__label", children: it.label }),
1252
+ it.meta != null ? /* @__PURE__ */ jsx("span", { className: "wp-nav__meta", children: it.meta }) : null
1423
1253
  ]
1424
- }
1425
- ),
1426
- open ? /* @__PURE__ */ jsx("div", { className: "wp-dp-pop", role: "dialog", "aria-label": "\uB0A0\uC9DC \uC120\uD0DD \uB2EC\uB825", children: /* @__PURE__ */ jsx("div", { className: "wp-dp-pop__body", children: /* @__PURE__ */ jsx(
1427
- Calendar,
1428
- {
1429
- monthCount: 1,
1430
- minDate,
1431
- maxDate,
1432
- focusDate,
1433
- onFocusDateChange: setFocusDate,
1434
- dayState: (date) => ({ selected: isSameDay(date, selectedDate) }),
1435
- onPick: (date) => {
1436
- const next = formatYmd(date);
1437
- if (!isControlled) setInnerValue(next);
1438
- onChange?.(next);
1439
- setOpen(false);
1440
- triggerRef.current?.focus();
1441
- }
1442
- }
1443
- ) }) }) : null
1444
- ] });
1254
+ },
1255
+ it.value
1256
+ ))
1257
+ ] }, s.label ? String(s.label) : si)) });
1445
1258
  }
1446
- function DateRangePicker({
1447
- value,
1448
- onChange,
1449
- min,
1450
- max,
1451
- invalid = false,
1452
- disabled = false
1453
- }) {
1454
- const [open, setOpen] = useState(false);
1455
- const [innerRange, setInnerRange] = useState({});
1456
- const hostRef = useRef(null);
1457
- const triggerRef = useRef(null);
1458
- const isControlled = value !== void 0;
1459
- const currentRange = (isControlled ? value : innerRange) ?? {};
1460
- const fromDate = useMemo(() => parseYmd(currentRange.from), [currentRange.from]);
1461
- const toDate = useMemo(() => parseYmd(currentRange.to), [currentRange.to]);
1462
- const minDate = useMemo(() => parseYmd(min), [min]);
1463
- const maxDate = useMemo(() => parseYmd(max), [max]);
1464
- const [focusDate, setFocusDate] = useState(() => fromDate ?? clampDate(/* @__PURE__ */ new Date(), minDate, maxDate));
1465
- const dismiss = useCallback((reason) => {
1466
- setOpen(false);
1467
- if (reason === "escape") triggerRef.current?.focus();
1468
- }, []);
1469
- useDismiss(open, hostRef, dismiss);
1470
- const hasValue = Boolean(currentRange.from || currentRange.to);
1471
- const label = hasValue ? `${currentRange.from ?? ""} ~ ${currentRange.to ?? ""}` : "\uAE30\uAC04 \uC120\uD0DD";
1472
- const isInvalid = Boolean(invalid);
1473
- const openCalendar = () => {
1474
- setFocusDate(fromDate ?? toDate ?? clampDate(/* @__PURE__ */ new Date(), minDate, maxDate));
1475
- setOpen(true);
1476
- };
1477
- const commit = (next) => {
1478
- if (!isControlled) setInnerRange(next);
1479
- onChange?.(next);
1480
- };
1481
- const pick = (date) => {
1482
- const ymd = formatYmd(date);
1483
- const startingOver = fromDate === void 0 || toDate !== void 0 || date.getTime() < fromDate.getTime();
1484
- if (startingOver) {
1485
- commit({ from: ymd, to: void 0 });
1486
- return;
1259
+ function Tooltip({ label, shortcut, placement = "top", wrap = false, children, className = "", ...rest }) {
1260
+ const [open, setOpen] = React.useState(false);
1261
+ const pos = {
1262
+ top: { bottom: "100%", left: "50%", transform: "translate(-50%,-7px)" },
1263
+ bottom: { top: "100%", left: "50%", transform: "translate(-50%,7px)" },
1264
+ left: { right: "100%", top: "50%", transform: "translate(-7px,-50%)" },
1265
+ right: { left: "100%", top: "50%", transform: "translate(7px,-50%)" }
1266
+ }[placement];
1267
+ const classes = ["wp-tooltip", "wp-tooltip--" + placement];
1268
+ if (wrap) classes.push("wp-tooltip--wrap");
1269
+ if (className) classes.push(className);
1270
+ return /* @__PURE__ */ jsxs(
1271
+ "span",
1272
+ {
1273
+ className: "wp-tooltip-host",
1274
+ onMouseEnter: () => setOpen(true),
1275
+ onMouseLeave: () => setOpen(false),
1276
+ onFocus: () => setOpen(true),
1277
+ onBlur: () => setOpen(false),
1278
+ ...rest,
1279
+ children: [
1280
+ children,
1281
+ open ? /* @__PURE__ */ jsxs("span", { className: classes.join(" "), style: pos, role: "tooltip", children: [
1282
+ label,
1283
+ shortcut ? /* @__PURE__ */ jsx("kbd", { className: "wp-tooltip__key", children: shortcut }) : null
1284
+ ] }) : null
1285
+ ]
1487
1286
  }
1488
- commit({ from: currentRange.from, to: ymd });
1489
- setOpen(false);
1490
- triggerRef.current?.focus();
1491
- };
1492
- return /* @__PURE__ */ jsxs("div", { ref: hostRef, className: "wp-dp-host", children: [
1493
- /* @__PURE__ */ jsx(HoistedStyle, { id: "wp-datepicker", css: DP_CSS }),
1494
- /* @__PURE__ */ jsxs(
1495
- "button",
1496
- {
1497
- ref: triggerRef,
1498
- type: "button",
1499
- className: triggerClassName("md", isInvalid),
1500
- "aria-invalid": isInvalid || void 0,
1501
- "aria-haspopup": "dialog",
1502
- "aria-expanded": open,
1503
- disabled,
1504
- onClick: () => open ? setOpen(false) : openCalendar(),
1505
- children: [
1506
- /* @__PURE__ */ jsx("span", { className: "wp-dp-trigger__icon", children: /* @__PURE__ */ jsx(Icon, { name: "calendar", size: 15 }) }),
1507
- /* @__PURE__ */ jsx("span", { className: `wp-dp-trigger__value${hasValue ? "" : " wp-dp-trigger__value--placeholder"}`, children: label })
1508
- ]
1509
- }
1510
- ),
1511
- open ? /* @__PURE__ */ jsx("div", { className: "wp-dp-pop wp-dp-pop--wide", role: "dialog", "aria-label": "\uAE30\uAC04 \uC120\uD0DD \uB2EC\uB825", children: /* @__PURE__ */ jsx("div", { className: "wp-dp-pop__body", children: /* @__PURE__ */ jsx(
1512
- Calendar,
1513
- {
1514
- monthCount: 2,
1515
- minDate,
1516
- maxDate,
1517
- focusDate,
1518
- onFocusDateChange: setFocusDate,
1519
- dayState: (date) => {
1520
- const t = date.getTime();
1521
- const start = fromDate?.getTime();
1522
- const end = toDate?.getTime();
1523
- if (start !== void 0 && end !== void 0 && t > start && t < end) return { rangeMiddle: true };
1524
- return {
1525
- rangeStart: start !== void 0 && t === start && end !== void 0,
1526
- rangeEnd: end !== void 0 && t === end,
1527
- // 아직 시작만 고른 상태는 단일 선택처럼 보인다
1528
- selected: start !== void 0 && t === start && end === void 0 || void 0
1529
- };
1530
- },
1531
- onPick: pick
1532
- }
1533
- ) }) }) : null
1534
- ] });
1287
+ );
1535
1288
  }
1536
- var DP_CSS = `
1537
- .wp-dp-host{position:relative}
1538
- .wp-dp-pop{position:absolute;top:calc(100% + var(--wp-space-2));left:0;min-width:100%;width:max-content;background:var(--wp-surface-card);border:1px solid var(--wp-border-subtle);border-radius:var(--wp-radius-lg);box-shadow:var(--wp-shadow-lg);z-index:300}
1539
- .wp-dp-pop--wide{max-width:min(640px,90vw)}
1540
- .wp-dp-pop__body{padding:var(--wp-space-4);max-height:60vh;overflow:auto}
1541
- .wp-dp-trigger{display:inline-flex;align-items:center;gap:var(--wp-space-2);text-align:left;cursor:pointer}
1542
- .wp-dp-trigger:disabled{cursor:not-allowed}
1543
- .wp-dp-trigger__icon{flex:none;display:inline-flex;color:var(--wp-text-muted)}
1544
- .wp-dp-trigger:disabled .wp-dp-trigger__icon{color:var(--wp-text-disabled)}
1545
- .wp-dp-trigger__value{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--wp-font-mono);font-size:12.5px;letter-spacing:-0.01em}
1546
- .wp-dp-trigger__value--placeholder{font-family:inherit;font-size:13px;letter-spacing:normal;color:var(--wp-text-subtle)}
1547
- .wp-dp{font-family:inherit;font-size:13px;color:var(--wp-text-default)}
1548
- .wp-dp__months{position:relative;display:flex;flex-wrap:wrap;gap:var(--wp-space-5)}
1549
- .wp-dp__nav{position:absolute;top:0;right:0;display:flex;gap:var(--wp-space-1);z-index:1}
1550
- .wp-dp__navbtn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:none;background:transparent;border-radius:var(--wp-radius-sm);color:var(--wp-text-muted);cursor:pointer;transition:background 0.12s,color 0.12s}
1551
- .wp-dp__navbtn:hover:not(:disabled){background:var(--wp-surface-hover);color:var(--wp-text-strong)}
1552
- .wp-dp__navbtn:focus-visible{outline:2px solid var(--wp-border-focus);outline-offset:1px}
1553
- .wp-dp__navbtn:disabled{color:var(--wp-text-disabled);cursor:default;background:transparent}
1554
- .wp-dp__caption{display:flex;align-items:center;height:28px;margin-bottom:var(--wp-space-2);padding-left:var(--wp-space-1)}
1555
- .wp-dp__caption-label{font-size:13px;font-weight:600;color:var(--wp-text-strong)}
1556
- .wp-dp__grid{border-collapse:collapse}
1557
- .wp-dp__weekday{width:32px;height:28px;padding:0;font-size:12px;font-weight:500;color:var(--wp-text-muted);text-align:center}
1558
- .wp-dp__weekday:first-child{color:var(--wp-text-danger)}
1559
- .wp-dp__day{padding:0;text-align:center}
1560
- .wp-dp__day-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:30px;padding:0;border:none;background:transparent;border-radius:var(--wp-radius-sm);font:inherit;font-variant-numeric:tabular-nums;color:inherit;cursor:pointer;transition:background 0.12s,color 0.12s}
1561
- .wp-dp__day:not(.wp-dp__day--selected):not(.wp-dp__day--disabled) .wp-dp__day-btn:hover{background:var(--wp-surface-hover)}
1562
- .wp-dp__day-btn:focus-visible{outline:2px solid var(--wp-border-focus);outline-offset:-1px}
1563
- .wp-dp__day--today .wp-dp__day-btn{box-shadow:inset 0 0 0 1px var(--wp-border-focus)}
1564
- .wp-dp__day--outside{color:var(--wp-text-subtle)}
1565
- .wp-dp__day--disabled{color:var(--wp-text-disabled)}
1566
- .wp-dp__day--disabled .wp-dp__day-btn{cursor:default}
1567
- .wp-dp__day--selected .wp-dp__day-btn{background:var(--wp-action-primary-bg);color:var(--wp-action-primary-fg);font-weight:500}
1568
- .wp-dp__day--selected.wp-dp__day--today .wp-dp__day-btn{box-shadow:none}
1569
- .wp-dp__day--range-middle .wp-dp__day-btn{background:var(--wp-surface-selected);color:var(--wp-text-default);border-radius:0;font-weight:400}
1570
- .wp-dp__day--range-start .wp-dp__day-btn,.wp-dp__day--range-end .wp-dp__day-btn{background:var(--wp-action-primary-bg);color:var(--wp-action-primary-fg);font-weight:500}
1571
- .wp-dp__day--range-start.wp-dp__day--today .wp-dp__day-btn,.wp-dp__day--range-end.wp-dp__day--today .wp-dp__day-btn{box-shadow:none}
1572
- `;
1573
1289
 
1574
- export { Alert, Badge, Button, Card, Checkbox, DatePicker, DateRangePicker, Dialog, EmptyState, Field, HoistedStyle, Icon, IconButton, Input, Pagination, ProgressBar, Select, Spinner, StatCard, Switch, Table, Tabs, Tag, Textarea, Toast };
1290
+ export { Alert, Avatar, Badge, Breadcrumb, Button, Card, Checkbox, Dialog, EmptyState, Field, Icon, IconButton, Input, Pagination, ProgressBar, Radio, SegmentedControl, Select, SidebarNav, Spinner, StatCard, Switch, Table, Tabs, Tag, Textarea, Toast, Tooltip };