@reopt-ai/opt-ui 1.9.0 → 1.11.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 (64) hide show
  1. package/COMPONENT_CATALOG.md +177 -66
  2. package/README.md +21 -5
  3. package/dist/core/index.cjs +106 -104
  4. package/dist/core/index.d.cts +3 -3
  5. package/dist/core/index.d.ts +3 -3
  6. package/dist/core/index.js +3 -3
  7. package/dist/docs/02-components/01-core.md +92 -41
  8. package/dist/docs/02-components/02-visuals.md +1 -1
  9. package/dist/docs/02-components/03-shells.md +96 -26
  10. package/dist/docs/02-components/04-surfaces.md +1 -1
  11. package/dist/docs/02-components/index.md +5 -5
  12. package/dist/{field-sidebar-B5vk3luQ.d.cts → field-sidebar-B5SQC35J.d.cts} +226 -3
  13. package/dist/field-sidebar-B5SQC35J.d.cts.map +1 -0
  14. package/dist/{field-sidebar-B7QkWvMG.js → field-sidebar-BXl5RJ3q.js} +599 -43
  15. package/dist/field-sidebar-BXl5RJ3q.js.map +1 -0
  16. package/dist/{field-sidebar-Dk9gJGA_.d.ts → field-sidebar-CBeWE8xX.d.ts} +226 -3
  17. package/dist/field-sidebar-CBeWE8xX.d.ts.map +1 -0
  18. package/dist/{field-sidebar-mFHemxBz.cjs → field-sidebar-DAuN4jPV.cjs} +883 -309
  19. package/dist/id-registry.cjs +46 -6
  20. package/dist/id-registry.d.cts.map +1 -1
  21. package/dist/id-registry.d.ts.map +1 -1
  22. package/dist/id-registry.js +46 -6
  23. package/dist/id-registry.js.map +1 -1
  24. package/dist/id-registry.json +97 -12
  25. package/dist/index.cjs +593 -587
  26. package/dist/index.d.cts +10 -6
  27. package/dist/index.d.cts.map +1 -1
  28. package/dist/index.d.ts +10 -6
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +20 -19
  31. package/dist/index.js.map +1 -1
  32. package/dist/{key-pad-menu-D8OS_VCT.d.cts → key-pad-menu-BxTy_u0Q.d.cts} +152 -51
  33. package/dist/key-pad-menu-BxTy_u0Q.d.cts.map +1 -0
  34. package/dist/{key-pad-menu-DoGskWbp.cjs → key-pad-menu-Cg6rZBie.cjs} +670 -923
  35. package/dist/{key-pad-menu-EEb6Ho5h.d.ts → key-pad-menu-u5GTJl9B.d.ts} +152 -51
  36. package/dist/key-pad-menu-u5GTJl9B.d.ts.map +1 -0
  37. package/dist/{key-pad-menu-BFd79JoS.js → key-pad-menu-wXkWn1I1.js} +500 -699
  38. package/dist/key-pad-menu-wXkWn1I1.js.map +1 -0
  39. package/dist/meta.cjs +486 -9
  40. package/dist/meta.d.cts.map +1 -1
  41. package/dist/meta.d.ts.map +1 -1
  42. package/dist/meta.js +486 -9
  43. package/dist/meta.js.map +1 -1
  44. package/dist/shells/index.cjs +4 -1
  45. package/dist/shells/index.d.cts +2 -2
  46. package/dist/shells/index.d.ts +2 -2
  47. package/dist/shells/index.js +2 -2
  48. package/dist/{highlight-CGcrYGMC.cjs → text-truncate-BZdL1k5Z.cjs} +608 -83
  49. package/dist/{highlight-C2sfnJN8.js → text-truncate-C17HHCR-.js} +534 -87
  50. package/dist/text-truncate-C17HHCR-.js.map +1 -0
  51. package/dist/{field-token-CSOrU5gl.d.ts → text-truncate-DW78lg4S.d.cts} +63 -4
  52. package/dist/text-truncate-DW78lg4S.d.cts.map +1 -0
  53. package/dist/{field-token-CSOrU5gl.d.cts → text-truncate-DW78lg4S.d.ts} +63 -4
  54. package/dist/text-truncate-DW78lg4S.d.ts.map +1 -0
  55. package/package.json +2 -2
  56. package/dist/field-sidebar-B5vk3luQ.d.cts.map +0 -1
  57. package/dist/field-sidebar-B7QkWvMG.js.map +0 -1
  58. package/dist/field-sidebar-Dk9gJGA_.d.ts.map +0 -1
  59. package/dist/field-token-CSOrU5gl.d.cts.map +0 -1
  60. package/dist/field-token-CSOrU5gl.d.ts.map +0 -1
  61. package/dist/highlight-C2sfnJN8.js.map +0 -1
  62. package/dist/key-pad-menu-BFd79JoS.js.map +0 -1
  63. package/dist/key-pad-menu-D8OS_VCT.d.cts.map +0 -1
  64. package/dist/key-pad-menu-EEb6Ho5h.d.ts.map +0 -1
@@ -142,6 +142,7 @@ const OPT_HOVER_ITEM = "[@media(any-hover:hover)]:hover:bg-accent-subtle active:
142
142
  const OPT_BORDER = "border border-border";
143
143
  const OPT_DIVIDER = "divide-border-subtle";
144
144
  const OPT_SURFACE = "rounded-lg bg-surface shadow-sm";
145
+ const OPT_SURFACE_RAISED = "rounded-xl bg-surface-raised shadow-md";
145
146
  const OPT_SURFACE_POPOVER = "z-50 rounded-lg border border-border bg-surface-overlay p-2 shadow-lg";
146
147
  const OPT_TEXT_PRIMARY = "text-text-primary";
147
148
  const OPT_TEXT_SECONDARY = "text-text-secondary";
@@ -240,44 +241,230 @@ function useControlledState(defaultValue, controlledValue, onChange) {
240
241
  }, [isControlled, onChange])];
241
242
  }
242
243
  //#endregion
244
+ //#region src/core/skeleton.tsx
245
+ const _excluded$17 = [
246
+ "variant",
247
+ "width",
248
+ "height",
249
+ "lines",
250
+ "animated",
251
+ "className",
252
+ "style"
253
+ ];
254
+ const _excluded2$9 = ["lines", "className"];
255
+ const _excluded3$8 = ["size", "className"];
256
+ const _excluded4$6 = ["className"];
257
+ const variantStyles$4 = {
258
+ text: "rounded h-4",
259
+ circular: "rounded-full",
260
+ rectangular: "rounded-lg"
261
+ };
262
+ /** Renders the skeleton component. */
263
+ function Skeleton(_ref) {
264
+ let { variant = "text", width, height, lines = 1, animated = true, className, style } = _ref, props = _objectWithoutProperties(_ref, _excluded$17);
265
+ const baseClass = cn("bg-bg-subtle", animated && "animate-pulse", variantStyles$4[variant], className);
266
+ const computedStyle = _objectSpread2({
267
+ width: typeof width === "number" ? `${width}px` : width,
268
+ height: typeof height === "number" ? `${height}px` : height
269
+ }, style);
270
+ if (variant === "text" && lines > 1) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
271
+ className: "gap-element flex flex-col",
272
+ role: "status",
273
+ "aria-label": "Loading",
274
+ "data-opt-id": "EJT87",
275
+ "data-opt-slug": "skeleton.Skeleton",
276
+ children: [Array.from({ length: lines }).map((_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", _objectSpread2({
277
+ className: cn(baseClass, i === lines - 1 && "w-4/5"),
278
+ style: i === lines - 1 ? void 0 : computedStyle
279
+ }, props), i)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
280
+ className: "sr-only",
281
+ children: "Loading..."
282
+ })]
283
+ });
284
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", _objectSpread2(_objectSpread2({
285
+ className: baseClass,
286
+ style: computedStyle,
287
+ role: "status",
288
+ "aria-label": "Loading"
289
+ }, props), {}, {
290
+ "data-opt-id": "EJT87",
291
+ "data-opt-slug": "skeleton.Skeleton",
292
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
293
+ className: "sr-only",
294
+ children: "Loading..."
295
+ })
296
+ }));
297
+ }
298
+ /** Renders the skeleton text component. */
299
+ function SkeletonText(_ref2) {
300
+ let { lines = 3, className } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$9);
301
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, _objectSpread2(_objectSpread2({
302
+ variant: "text",
303
+ lines,
304
+ className
305
+ }, props), {}, {
306
+ "data-opt-id": "MX3D5",
307
+ "data-opt-slug": "skeleton.SkeletonText"
308
+ }));
309
+ }
310
+ /** Renders the skeleton avatar component. */
311
+ function SkeletonAvatar(_ref3) {
312
+ let { size = 40, className } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$8);
313
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, _objectSpread2(_objectSpread2({
314
+ variant: "circular",
315
+ width: size,
316
+ height: size,
317
+ className
318
+ }, props), {}, {
319
+ "data-opt-id": "MP0HZ",
320
+ "data-opt-slug": "skeleton.SkeletonAvatar"
321
+ }));
322
+ }
323
+ /** Renders the skeleton card component. */
324
+ function SkeletonCard(_ref4) {
325
+ let { className } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4$6);
326
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", _objectSpread2(_objectSpread2({ className: cn("gap-group flex flex-col", className) }, props), {}, {
327
+ "data-opt-id": "34V5D",
328
+ "data-opt-slug": "skeleton.SkeletonCard",
329
+ children: [
330
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, {
331
+ variant: "rectangular",
332
+ height: 120
333
+ }),
334
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, {
335
+ variant: "text",
336
+ width: "60%"
337
+ }),
338
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, {
339
+ variant: "text",
340
+ lines: 2
341
+ })
342
+ ]
343
+ }));
344
+ }
345
+ /** Renders the skeleton table component. */
346
+ function SkeletonTable({ rows = 5, columns = 4, className }) {
347
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
348
+ className: cn("gap-element flex flex-col", className),
349
+ role: "status",
350
+ "aria-label": "Loading table",
351
+ "data-opt-id": "3KEDN",
352
+ "data-opt-slug": "skeleton.SkeletonTable",
353
+ children: [
354
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
355
+ className: "border-border-subtle gap-group flex border-b pb-2",
356
+ children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, {
357
+ variant: "text",
358
+ className: "flex-1",
359
+ height: 16
360
+ }, i))
361
+ }),
362
+ Array.from({ length: rows }).map((_, rowIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
363
+ className: "gap-group flex py-2",
364
+ children: Array.from({ length: columns }).map((_, colIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, {
365
+ variant: "text",
366
+ className: "flex-1",
367
+ height: 14
368
+ }, colIndex))
369
+ }, rowIndex)),
370
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
371
+ className: "sr-only",
372
+ children: "Loading..."
373
+ })
374
+ ]
375
+ });
376
+ }
377
+ //#endregion
243
378
  //#region src/core/stat-card.tsx
379
+ const TREND_GLYPH = {
380
+ up: "↑",
381
+ down: "↓",
382
+ neutral: "→"
383
+ };
384
+ /**
385
+ * Colour follows meaning, not direction. A rising bounce rate is a fall in
386
+ * quality, so a card declaring `polarity: "negative"` inverts the palette
387
+ * rather than congratulating the reader on a worse number.
388
+ */
389
+ function deltaToneClass(trend, polarity) {
390
+ if (trend === "neutral") return OPT_TEXT_TERTIARY;
391
+ return (polarity === "positive" ? trend === "up" : trend === "down") ? "text-success-fg" : "text-danger-fg";
392
+ }
393
+ function sparkStroke(trend, polarity) {
394
+ if (!trend || trend === "neutral") return "var(--opt-chart-1)";
395
+ return (polarity === "positive" ? trend === "up" : trend === "down") ? "var(--opt-chart-diverging-positive)" : "var(--opt-chart-diverging-negative)";
396
+ }
244
397
  /** Renders the stat card component. */
245
- function StatCard({ title, value, change, trend, sparklineData, className }) {
246
- const trendColor = trend === "up" ? "text-success-fg" : trend === "down" ? "text-danger-fg" : "text-text-tertiary";
247
- const trendIcon = trend === "up" ? "↑" : trend === "down" ? "↓" : "→";
248
- const sparkColor = trend === "up" ? "var(--opt-chart-diverging-positive)" : trend === "down" ? "var(--opt-chart-diverging-negative)" : "var(--opt-chart-1)";
249
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
250
- className: cn(OPT_SURFACE, OPT_BORDER, "flex flex-col gap-1 p-5", className),
251
- "data-opt-id": "GAX47",
252
- "data-opt-slug": "stat-card.StatCard",
253
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
254
- className: "flex items-start justify-between gap-4",
255
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
256
- className: "flex min-w-0 flex-col gap-1",
257
- children: [
258
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
259
- className: cn(OPT_TEXT_SECONDARY, "truncate text-sm"),
260
- children: title
261
- }),
262
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
263
- className: cn(OPT_TEXT_PRIMARY, "text-2xl font-bold"),
264
- children: value
265
- }),
266
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
267
- className: cn("text-sm font-medium", trendColor),
268
- children: [
269
- trendIcon,
270
- " ",
271
- change
272
- ]
273
- })
274
- ]
275
- }), sparklineData && sparklineData.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MiniSparkline, {
276
- data: sparklineData,
277
- color: sparkColor
278
- })]
279
- })
398
+ function StatCard({ title, value, change, trend, polarity = "positive", description, hint, sparklineData, size = "md", loading = false, href, onSelect, selected = false, className }) {
399
+ const titleId = react.useId();
400
+ const hintId = react.useId();
401
+ const hasDelta = Boolean(change) && trend !== void 0;
402
+ const interactive = Boolean(href || onSelect);
403
+ const body = loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
404
+ className: "flex flex-col gap-2",
405
+ children: [
406
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, { className: "h-4 w-24" }),
407
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, { className: "h-7 w-32" }),
408
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, { className: "h-3 w-20" })
409
+ ]
410
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
411
+ className: "flex items-start justify-between gap-4",
412
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
413
+ className: "flex min-w-0 flex-col gap-1",
414
+ children: [
415
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
416
+ id: titleId,
417
+ className: cn(OPT_TEXT_SECONDARY, "truncate text-sm"),
418
+ children: title
419
+ }),
420
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
421
+ className: cn(OPT_TEXT_PRIMARY, "font-bold tabular-nums", size === "sm" ? "text-xl" : "text-2xl"),
422
+ children: value
423
+ }),
424
+ hasDelta && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
425
+ className: cn("text-sm font-medium tabular-nums", deltaToneClass(trend, polarity)),
426
+ children: [
427
+ TREND_GLYPH[trend],
428
+ " ",
429
+ change
430
+ ]
431
+ }),
432
+ description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
433
+ className: cn("text-text-tertiary", "text-xs"),
434
+ children: description
435
+ }),
436
+ hint && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
437
+ id: hintId,
438
+ className: "sr-only",
439
+ children: hint
440
+ })
441
+ ]
442
+ }), sparklineData && sparklineData.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MiniSparkline, {
443
+ data: sparklineData,
444
+ color: sparkStroke(trend, polarity)
445
+ })]
280
446
  });
447
+ const shared = {
448
+ className: cn(OPT_SURFACE, OPT_BORDER, "flex flex-col gap-1", size === "sm" ? "p-4" : "p-5", interactive && [
449
+ "hover:border-border-hover",
450
+ "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset",
451
+ "cursor-pointer text-left transition-colors"
452
+ ], selected && "border-accent", className),
453
+ title: hint,
454
+ "aria-describedby": hint ? hintId : void 0,
455
+ "data-opt-id": "GAX47",
456
+ "data-opt-slug": "stat-card.StatCard"
457
+ };
458
+ if (href) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", _objectSpread2(_objectSpread2({
459
+ href,
460
+ "aria-current": selected ? "true" : void 0
461
+ }, shared), {}, { children: body }));
462
+ if (onSelect) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", _objectSpread2(_objectSpread2({
463
+ type: "button",
464
+ onClick: onSelect,
465
+ "aria-pressed": selected
466
+ }, shared), {}, { children: body }));
467
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", _objectSpread2(_objectSpread2({}, shared), {}, { children: body }));
281
468
  }
282
469
  function MiniSparkline({ data, color }) {
283
470
  const width = 80;
@@ -329,7 +516,7 @@ const koBreadcrumbLabels = {
329
516
  navAriaLabel: "{label}(으)로 이동" };
330
517
  //#endregion
331
518
  //#region src/core/button.tsx
332
- const _excluded$15 = [
519
+ const _excluded$16 = [
333
520
  "variant",
334
521
  "size",
335
522
  "loading",
@@ -340,24 +527,24 @@ const _excluded$15 = [
340
527
  "children",
341
528
  "aria-busy"
342
529
  ];
343
- const variantStyles$2 = {
530
+ const variantStyles$3 = {
344
531
  primary: "bg-accent text-accent-fg hover:bg-accent-hover active:bg-accent-active focus-visible:ring-offset-2",
345
532
  secondary: "border border-border bg-surface text-text-primary hover:bg-bg-subtle active:bg-bg-muted focus-visible:ring-offset-1",
346
533
  ghost: "text-text-secondary hover:bg-bg-subtle active:bg-bg-muted focus-visible:ring-offset-1",
347
534
  danger: "bg-danger text-danger-fg hover:bg-danger active:bg-danger focus-visible:ring-offset-2"
348
535
  };
349
- const sizeStyles$4 = {
536
+ const sizeStyles$5 = {
350
537
  sm: "h-[var(--opt-control-sm)] px-[var(--opt-control-padding-sm)] text-xs gap-[var(--opt-space-1-5)]",
351
538
  md: "h-[var(--opt-control-md)] px-[var(--opt-control-padding-md)] text-sm gap-[var(--opt-space-2)]",
352
539
  lg: "h-[var(--opt-control-lg)] px-[var(--opt-control-padding-lg)] text-base gap-[var(--opt-space-2)]"
353
540
  };
354
541
  /** Renders the button component. */
355
542
  function Button(_ref) {
356
- let { variant = "primary", size = "md", loading = false, leftIcon, rightIcon, className, disabled, children, "aria-busy": ariaBusy } = _ref, props = _objectWithoutProperties(_ref, _excluded$15);
543
+ let { variant = "primary", size = "md", loading = false, leftIcon, rightIcon, className, disabled, children, "aria-busy": ariaBusy } = _ref, props = _objectWithoutProperties(_ref, _excluded$16);
357
544
  const isDisabled = disabled || loading;
358
545
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", _objectSpread2(_objectSpread2({
359
546
  type: "button",
360
- className: cn("inline-flex cursor-pointer items-center justify-center rounded-lg font-medium transition-colors", OPT_FOCUS_VISIBLE, variantStyles$2[variant], sizeStyles$4[size], isDisabled && "pointer-events-none cursor-not-allowed opacity-50", className),
547
+ className: cn("inline-flex cursor-pointer items-center justify-center rounded-lg font-medium transition-colors", OPT_FOCUS_VISIBLE, variantStyles$3[variant], sizeStyles$5[size], isDisabled && "pointer-events-none cursor-not-allowed opacity-50", className),
361
548
  disabled: isDisabled
362
549
  }, props), {}, {
363
550
  "aria-busy": loading ? true : ariaBusy,
@@ -399,44 +586,68 @@ const iconSizeClasses = {
399
586
  md: "text-4xl",
400
587
  lg: "text-5xl"
401
588
  };
589
+ const titleSizeClasses = {
590
+ sm: "text-base font-semibold",
591
+ md: "text-lg font-semibold",
592
+ lg: "text-xl font-semibold"
593
+ };
594
+ const iconToneClasses = {
595
+ default: OPT_TEXT_TERTIARY,
596
+ subdued: OPT_TEXT_TERTIARY,
597
+ error: "text-danger-fg"
598
+ };
599
+ function isActionList(actions) {
600
+ return Array.isArray(actions) && actions.every((entry) => typeof entry === "object" && entry !== null && "onClick" in entry);
601
+ }
402
602
  /** Renders the empty state component. */
403
- function EmptyState({ icon, title, description, actions, className, iconSize = "md", headingLevel = "h3" }) {
603
+ function EmptyState({ icon, title, description, body, footer, actions, className, iconSize = "md", headingLevel = "h3", titleSize = "md", layout = "vertical", hasBorder = false, tone = "default" }) {
404
604
  const HeadingTag = headingLevel;
605
+ const horizontal = layout === "horizontal";
606
+ const hasActions = isActionList(actions) ? actions.length > 0 : Boolean(actions);
405
607
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
406
- role: "status",
608
+ role: tone === "error" ? "alert" : "status",
407
609
  "aria-label": title,
408
- className: cn("flex flex-col items-center justify-center px-4 py-12 text-center", className),
409
- "data-opt-id": "5ZK92",
610
+ className: cn("flex px-4 py-12", horizontal ? "flex-row items-center justify-center gap-8 text-left" : "flex-col items-center justify-center text-center", hasBorder && ["border border-border", "rounded-xl"], tone === "subdued" && "bg-bg-subtle", className),
611
+ "data-opt-id": "MZV19",
410
612
  "data-opt-slug": "empty-state.EmptyState",
411
- children: [
412
- icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
413
- className: cn(`mb-4 text-text-tertiary`, iconSizeClasses[iconSize]),
414
- "aria-hidden": "true",
415
- children: icon
416
- }),
417
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HeadingTag, {
418
- className: `text-lg font-semibold ${OPT_TEXT_PRIMARY}`,
419
- children: title
420
- }),
421
- description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
422
- className: `mt-2 max-w-sm text-sm text-text-secondary`,
423
- children: description
424
- }),
425
- actions && actions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
426
- className: "mt-6 flex items-center gap-3",
427
- children: actions.map((action) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
428
- onClick: action.onClick,
429
- disabled: action.disabled,
430
- variant: action.variant === "secondary" ? "secondary" : "primary",
431
- children: action.label
432
- }, action.id))
433
- })
434
- ]
613
+ children: [icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
614
+ className: cn(iconToneClasses[tone], iconSizeClasses[iconSize], horizontal ? "shrink-0" : "mb-4"),
615
+ "aria-hidden": "true",
616
+ children: icon
617
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
618
+ className: cn("flex flex-col", horizontal ? "items-start" : "items-center"),
619
+ children: [
620
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HeadingTag, {
621
+ className: cn(titleSizeClasses[titleSize], OPT_TEXT_PRIMARY),
622
+ children: title
623
+ }),
624
+ body ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
625
+ className: cn("mt-2 max-w-md text-sm", OPT_TEXT_SECONDARY),
626
+ children: body
627
+ }) : description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
628
+ className: cn("mt-2 max-w-sm text-sm", "text-text-secondary"),
629
+ children: description
630
+ }),
631
+ hasActions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
632
+ className: cn("mt-6 flex flex-wrap items-center gap-3", !horizontal && "justify-center"),
633
+ children: isActionList(actions) ? actions.map((action) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
634
+ onClick: action.onClick,
635
+ disabled: action.disabled,
636
+ variant: action.variant === "secondary" ? "secondary" : "primary",
637
+ children: action.label
638
+ }, action.id)) : actions
639
+ }),
640
+ footer && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
641
+ className: cn("border-border-subtle mt-6 w-full border-t pt-4 text-sm", "text-text-tertiary"),
642
+ children: footer
643
+ })
644
+ ]
645
+ })]
435
646
  });
436
647
  }
437
648
  //#endregion
438
649
  //#region src/core/badge.tsx
439
- const _excluded$14 = [
650
+ const _excluded$15 = [
440
651
  "variant",
441
652
  "size",
442
653
  "dot",
@@ -445,7 +656,7 @@ const _excluded$14 = [
445
656
  "className",
446
657
  "children"
447
658
  ];
448
- const variantStyles$1 = {
659
+ const variantStyles$2 = {
449
660
  default: "bg-bg-subtle text-text-secondary",
450
661
  success: "bg-success-subtle text-success-fg",
451
662
  warning: "bg-warning-subtle text-warning-fg",
@@ -466,19 +677,19 @@ const progressStroke = {
466
677
  error: "stroke-danger",
467
678
  info: "stroke-info"
468
679
  };
469
- const sizeStyles$3 = {
680
+ const sizeStyles$4 = {
470
681
  sm: "px-1.5 py-0.5 text-[10px]",
471
682
  md: "px-2 py-0.5 text-[11px]"
472
683
  };
473
684
  /** Renders the badge component. */
474
685
  function Badge(_ref) {
475
- let { variant = "default", size = "md", dot = false, progress, progressSize = 16, className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$14);
686
+ let { variant = "default", size = "md", dot = false, progress, progressSize = 16, className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$15);
476
687
  const hasProgress = progress != null;
477
688
  const clampedProgress = hasProgress ? Math.min(100, Math.max(0, progress)) : 0;
478
689
  const radius = (progressSize - 3) / 2;
479
690
  const circumference = 2 * Math.PI * radius;
480
691
  const offset = circumference - clampedProgress / 100 * circumference;
481
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", _objectSpread2(_objectSpread2({ className: cn(OPT_BADGE, variantStyles$1[variant], sizeStyles$3[size], className) }, props), {}, {
692
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", _objectSpread2(_objectSpread2({ className: cn(OPT_BADGE, variantStyles$2[variant], sizeStyles$4[size], className) }, props), {}, {
482
693
  "data-opt-id": "9GBGZ",
483
694
  "data-opt-slug": "badge.Badge",
484
695
  children: [
@@ -518,24 +729,24 @@ function Badge(_ref) {
518
729
  }
519
730
  //#endregion
520
731
  //#region src/core/spinner.tsx
521
- const _excluded$13 = [
732
+ const _excluded$14 = [
522
733
  "size",
523
734
  "className",
524
735
  "role",
525
736
  "aria-hidden",
526
737
  "aria-label"
527
738
  ];
528
- const sizeStyles$2 = {
739
+ const sizeStyles$3 = {
529
740
  sm: "h-4 w-4",
530
741
  md: "h-6 w-6",
531
742
  lg: "h-8 w-8"
532
743
  };
533
744
  /** Renders the spinner component. */
534
745
  function Spinner(_ref) {
535
- let { size = "md", className, role, "aria-hidden": ariaHidden, "aria-label": ariaLabel } = _ref, props = _objectWithoutProperties(_ref, _excluded$13);
746
+ let { size = "md", className, role, "aria-hidden": ariaHidden, "aria-label": ariaLabel } = _ref, props = _objectWithoutProperties(_ref, _excluded$14);
536
747
  const isDecorative = ariaHidden === true || ariaHidden === "true";
537
748
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", _objectSpread2(_objectSpread2({
538
- className: cn("animate-spin text-current", sizeStyles$2[size], className),
749
+ className: cn("animate-spin text-current", sizeStyles$3[size], className),
539
750
  viewBox: "0 0 24 24",
540
751
  fill: "none",
541
752
  role: isDecorative ? void 0 : role !== null && role !== void 0 ? role : "status",
@@ -560,7 +771,7 @@ function Spinner(_ref) {
560
771
  }
561
772
  //#endregion
562
773
  //#region src/core/alert.tsx
563
- const _excluded$12 = [
774
+ const _excluded$13 = [
564
775
  "variant",
565
776
  "title",
566
777
  "icon",
@@ -569,7 +780,7 @@ const _excluded$12 = [
569
780
  "className",
570
781
  "children"
571
782
  ];
572
- const variantStyles = {
783
+ const variantStyles$1 = {
573
784
  info: "border-info bg-info-subtle text-info-fg",
574
785
  success: "border-success bg-success-subtle text-success-fg",
575
786
  warning: "border-warning bg-warning-subtle text-warning-fg",
@@ -629,11 +840,11 @@ const defaultIcons = {
629
840
  };
630
841
  /** Renders the alert component. */
631
842
  function Alert(_ref) {
632
- let { variant = "info", title, icon, dismissible = false, onDismiss, className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$12);
843
+ let { variant = "info", title, icon, dismissible = false, onDismiss, className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$13);
633
844
  const displayIcon = icon !== null && icon !== void 0 ? icon : defaultIcons[variant];
634
845
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", _objectSpread2(_objectSpread2({
635
846
  role: "alert",
636
- className: cn("relative rounded-lg border p-4", variantStyles[variant], className)
847
+ className: cn("relative rounded-lg border p-4", variantStyles$1[variant], className)
637
848
  }, props), {}, {
638
849
  "data-opt-id": "4SPK6",
639
850
  "data-opt-slug": "alert.Alert",
@@ -685,7 +896,7 @@ function useInputId(id, label, prefix) {
685
896
  }
686
897
  //#endregion
687
898
  //#region src/core/input.tsx
688
- const _excluded$11 = [
899
+ const _excluded$12 = [
689
900
  "label",
690
901
  "error",
691
902
  "hint",
@@ -700,7 +911,7 @@ const _excluded$11 = [
700
911
  const inputSizeStyles = OPT_INPUT_SIZE;
701
912
  const Input = (0, react.forwardRef)((_ref, ref) => {
702
913
  var _useInputId;
703
- let { label, error, hint, leftIcon, rightIcon, fullWidth = false, size = "md", required, className, id } = _ref, props = _objectWithoutProperties(_ref, _excluded$11);
914
+ let { label, error, hint, leftIcon, rightIcon, fullWidth = false, size = "md", required, className, id } = _ref, props = _objectWithoutProperties(_ref, _excluded$12);
704
915
  const fallbackId = (0, react.useId)().replace(/:/g, "");
705
916
  const inputId = (_useInputId = useInputId(id, label, "input")) !== null && _useInputId !== void 0 ? _useInputId : `input-${fallbackId}`;
706
917
  const hasError = Boolean(error);
@@ -850,6 +1061,65 @@ function StarRating({ value = 0, onChange, max = 5, readOnly = false, size = "md
850
1061
  });
851
1062
  }
852
1063
  //#endregion
1064
+ //#region src/core/meter.tsx
1065
+ const _excluded$11 = [
1066
+ "value",
1067
+ "min",
1068
+ "max",
1069
+ "size",
1070
+ "variant",
1071
+ "showValue",
1072
+ "label",
1073
+ "getValueLabel",
1074
+ "className"
1075
+ ];
1076
+ const sizeStyles$2 = {
1077
+ sm: "h-1",
1078
+ md: "h-2",
1079
+ lg: "h-3"
1080
+ };
1081
+ const variantStyles = {
1082
+ default: "bg-accent",
1083
+ success: "bg-success",
1084
+ warning: "bg-warning",
1085
+ error: "bg-danger"
1086
+ };
1087
+ /**
1088
+ * A scalar measurement within a known range (disk usage, score, capacity) —
1089
+ * `role="meter"`, distinct from Progress (task completion). Built on the
1090
+ * opt-ui-primitives Meter primitive, which owns the role/aria/valuetext.
1091
+ */
1092
+ function Meter(_ref) {
1093
+ let { value, min = 0, max = 100, size = "md", variant = "default", showValue = false, label, getValueLabel, className } = _ref, props = _objectWithoutProperties(_ref, _excluded$11);
1094
+ const clamped = Math.min(Math.max(value, min), max);
1095
+ const percentage = max === min ? 0 : (clamped - min) / (max - min) * 100;
1096
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", _objectSpread2(_objectSpread2({ className: cn("w-full", className) }, props), {}, {
1097
+ "data-opt-id": "G01TE",
1098
+ "data-opt-slug": "meter.Meter",
1099
+ children: [(showValue || label) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1100
+ className: "mb-1.5 flex items-center justify-between text-sm",
1101
+ children: [label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1102
+ className: "text-text-primary font-medium",
1103
+ children: label
1104
+ }), showValue && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1105
+ className: "text-text-tertiary",
1106
+ children: [Math.round(percentage), "%"]
1107
+ })]
1108
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_reopt_ai_opt_ui_primitives.Meter, {
1109
+ value: clamped,
1110
+ min,
1111
+ max,
1112
+ getValueLabel,
1113
+ "aria-label": label !== null && label !== void 0 ? label : `${Math.round(percentage)}%`,
1114
+ className: cn("bg-bg-subtle w-full overflow-hidden rounded-full", sizeStyles$2[size]),
1115
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1116
+ className: cn("h-full rounded-full transition-all duration-300 ease-out", variantStyles[variant]),
1117
+ style: { width: `${percentage}%` }
1118
+ })
1119
+ })]
1120
+ }));
1121
+ }
1122
+ //#endregion
853
1123
  //#region src/core/composite-zone.tsx
854
1124
  /** Renders the composite zone component. */
855
1125
  function CompositeZone({ children, label, focusLoop = true, focusWrap = true, className }) {
@@ -3532,6 +3802,55 @@ function FormDateRangePicker(_ref35) {
3532
3802
  }));
3533
3803
  }
3534
3804
  //#endregion
3805
+ //#region src/lib/formatters.ts
3806
+ const OPT_UI_DEFAULT_LOCALE = "ko-KR";
3807
+ const KST_OFFSET_MS = 324e5;
3808
+ function getKstDateParts(input) {
3809
+ const date = input instanceof Date ? input : new Date(input);
3810
+ if (Number.isNaN(date.getTime())) return null;
3811
+ const kstDate = new Date(date.getTime() + KST_OFFSET_MS);
3812
+ return {
3813
+ year: kstDate.getUTCFullYear(),
3814
+ month: kstDate.getUTCMonth() + 1,
3815
+ day: kstDate.getUTCDate(),
3816
+ hour: kstDate.getUTCHours(),
3817
+ minute: kstDate.getUTCMinutes(),
3818
+ second: kstDate.getUTCSeconds()
3819
+ };
3820
+ }
3821
+ function pad2(value) {
3822
+ return String(value).padStart(2, "0");
3823
+ }
3824
+ function meridiem(hour) {
3825
+ return hour < 12 ? "오전" : "오후";
3826
+ }
3827
+ function hour12(hour) {
3828
+ const normalized = hour % 12;
3829
+ return normalized === 0 ? 12 : normalized;
3830
+ }
3831
+ /** Formats a date as Korean short date text in the opt-ui default timezone. */
3832
+ function formatOptShortDate(input) {
3833
+ const parts = getKstDateParts(input);
3834
+ if (!parts) return "-";
3835
+ return `${parts.month}월 ${parts.day}일`;
3836
+ }
3837
+ /** Formats a date as Korean clock time in the opt-ui default timezone. */
3838
+ function formatOptTime(input) {
3839
+ const parts = getKstDateParts(input);
3840
+ if (!parts) return "-";
3841
+ return `${meridiem(parts.hour)} ${pad2(hour12(parts.hour))}:${pad2(parts.minute)}`;
3842
+ }
3843
+ /** Formats a date as Korean date-time text in the opt-ui default timezone. */
3844
+ function formatOptDateTime(input) {
3845
+ const parts = getKstDateParts(input);
3846
+ if (!parts) return "-";
3847
+ return `${parts.year}. ${parts.month}. ${parts.day}. ${meridiem(parts.hour)} ${hour12(parts.hour)}:${pad2(parts.minute)}:${pad2(parts.second)}`;
3848
+ }
3849
+ /** Formats numbers without depending on the runtime default locale. */
3850
+ function formatOptNumber(value) {
3851
+ return new Intl.NumberFormat(OPT_UI_DEFAULT_LOCALE).format(value);
3852
+ }
3853
+ //#endregion
3535
3854
  //#region src/core/checkbox.tsx
3536
3855
  const _excluded$1 = [
3537
3856
  "label",
@@ -4119,6 +4438,134 @@ function Highlight({ text, search, caseSensitive = false, firstOnly = false, cla
4119
4438
  });
4120
4439
  }
4121
4440
  //#endregion
4441
+ //#region src/core/text-truncate.tsx
4442
+ const useIsomorphicLayoutEffect = typeof window === "undefined" ? react.useEffect : react.useLayoutEffect;
4443
+ /** Measures text in the element's own resolved font, not an assumed one. */
4444
+ function createMeasurer(element) {
4445
+ const context = document.createElement("canvas").getContext("2d");
4446
+ if (!context) return null;
4447
+ const computed = window.getComputedStyle(element);
4448
+ context.font = [
4449
+ computed.fontStyle,
4450
+ computed.fontVariant,
4451
+ computed.fontWeight,
4452
+ `${computed.fontSize}/${computed.lineHeight}`,
4453
+ computed.fontFamily
4454
+ ].join(" ");
4455
+ const spacing = Number.parseFloat(computed.letterSpacing) || 0;
4456
+ return (value) => context.measureText(value).width + spacing * value.length;
4457
+ }
4458
+ /** Largest `n` in `[0, max]` for which `fits(n)` holds. */
4459
+ function largestFitting(max, fits) {
4460
+ let low = 0;
4461
+ let high = max;
4462
+ while (low < high) {
4463
+ const mid = Math.ceil((low + high) / 2);
4464
+ if (fits(mid)) low = mid;
4465
+ else high = mid - 1;
4466
+ }
4467
+ return low;
4468
+ }
4469
+ function truncateToWidth(text, side, ellipsis, available, measure) {
4470
+ if (measure(text) <= available) return text;
4471
+ const chars = Array.from(text);
4472
+ if (side === "end") {
4473
+ const keep = largestFitting(chars.length, (n) => measure(chars.slice(0, n).join("") + ellipsis) <= available);
4474
+ return chars.slice(0, keep).join("") + ellipsis;
4475
+ }
4476
+ if (side === "start") {
4477
+ const keep = largestFitting(chars.length, (n) => measure(ellipsis + chars.slice(chars.length - n).join("")) <= available);
4478
+ return ellipsis + chars.slice(chars.length - keep).join("");
4479
+ }
4480
+ if (side === "startEnd") {
4481
+ const keep = largestFitting(Math.floor(chars.length / 2), (n) => {
4482
+ const head = chars.slice(0, n).join("");
4483
+ const tail = chars.slice(chars.length - n).join("");
4484
+ return measure(head + ellipsis + tail) <= available;
4485
+ });
4486
+ if (keep === 0) return ellipsis;
4487
+ return chars.slice(0, keep).join("") + ellipsis + chars.slice(chars.length - keep).join("");
4488
+ }
4489
+ const span = largestFitting(chars.length, (n) => {
4490
+ const start = Math.floor((chars.length - n) / 2);
4491
+ return measure(ellipsis + chars.slice(start, start + n).join("") + ellipsis) <= available;
4492
+ });
4493
+ if (span === 0) return ellipsis;
4494
+ const start = Math.floor((chars.length - span) / 2);
4495
+ return ellipsis + chars.slice(start, start + span).join("") + ellipsis;
4496
+ }
4497
+ /**
4498
+ * TextTruncate — drops characters from the part of a string that identifies it
4499
+ * least.
4500
+ *
4501
+ * CSS can only cut the end. That is the wrong end for the strings analytics
4502
+ * shows most: two URLs that differ in their query string, two ids that share a
4503
+ * prefix, a stack frame whose filename is at the tail. This measures the real
4504
+ * text in the real font against the real available width and cuts where the
4505
+ * caller says.
4506
+ *
4507
+ * The full string stays in the accessibility tree and in `title`, so
4508
+ * truncation never costs the reader information — only space.
4509
+ *
4510
+ * @example
4511
+ * ```tsx
4512
+ * <TextTruncate text={event.url} truncation="startEnd" />
4513
+ * ```
4514
+ */
4515
+ function TextTruncate({ text, truncation = "startEnd", ellipsis = "…", width, children, className }) {
4516
+ const ref = (0, react.useRef)(null);
4517
+ const [available, setAvailable] = (0, react.useState)(width !== null && width !== void 0 ? width : null);
4518
+ useIsomorphicLayoutEffect(() => {
4519
+ if (width !== void 0) {
4520
+ setAvailable(width);
4521
+ return;
4522
+ }
4523
+ const element = ref.current;
4524
+ if (!element || typeof ResizeObserver === "undefined") return;
4525
+ const observer = new ResizeObserver((entries) => {
4526
+ const entry = entries[0];
4527
+ if (entry) setAvailable(entry.contentRect.width);
4528
+ });
4529
+ observer.observe(element);
4530
+ setAvailable(element.getBoundingClientRect().width);
4531
+ return () => observer.disconnect();
4532
+ }, [width]);
4533
+ const [rendered, setRendered] = (0, react.useState)(text);
4534
+ useIsomorphicLayoutEffect(() => {
4535
+ const element = ref.current;
4536
+ if (!element || available === null || available <= 0) {
4537
+ setRendered(text);
4538
+ return;
4539
+ }
4540
+ const measure = createMeasurer(element);
4541
+ if (!measure) {
4542
+ setRendered(text);
4543
+ return;
4544
+ }
4545
+ setRendered(truncateToWidth(text, truncation, ellipsis, available, measure));
4546
+ }, [
4547
+ text,
4548
+ truncation,
4549
+ ellipsis,
4550
+ available
4551
+ ]);
4552
+ const truncated = rendered !== text;
4553
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4554
+ ref,
4555
+ className: cn("block w-full overflow-hidden whitespace-nowrap", className),
4556
+ title: truncated ? text : void 0,
4557
+ "data-opt-id": "Y6BGX",
4558
+ "data-opt-slug": "text-truncate.TextTruncate",
4559
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4560
+ "aria-hidden": truncated ? "true" : void 0,
4561
+ children: children ? children(rendered) : rendered
4562
+ }), truncated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4563
+ className: "sr-only",
4564
+ children: text
4565
+ })]
4566
+ });
4567
+ }
4568
+ //#endregion
4122
4569
  Object.defineProperty(exports, "Alert", {
4123
4570
  enumerable: true,
4124
4571
  get: function() {
@@ -4575,6 +5022,12 @@ Object.defineProperty(exports, "MenubarRoot", {
4575
5022
  return MenubarRoot;
4576
5023
  }
4577
5024
  });
5025
+ Object.defineProperty(exports, "Meter", {
5026
+ enumerable: true,
5027
+ get: function() {
5028
+ return Meter;
5029
+ }
5030
+ });
4578
5031
  Object.defineProperty(exports, "NumberInput", {
4579
5032
  enumerable: true,
4580
5033
  get: function() {
@@ -4725,6 +5178,12 @@ Object.defineProperty(exports, "OPT_SURFACE_POPOVER", {
4725
5178
  return OPT_SURFACE_POPOVER;
4726
5179
  }
4727
5180
  });
5181
+ Object.defineProperty(exports, "OPT_SURFACE_RAISED", {
5182
+ enumerable: true,
5183
+ get: function() {
5184
+ return OPT_SURFACE_RAISED;
5185
+ }
5186
+ });
4728
5187
  Object.defineProperty(exports, "OPT_TABLE_ROW_ACTIVE", {
4729
5188
  enumerable: true,
4730
5189
  get: function() {
@@ -4779,6 +5238,12 @@ Object.defineProperty(exports, "OPT_TH", {
4779
5238
  return OPT_TH;
4780
5239
  }
4781
5240
  });
5241
+ Object.defineProperty(exports, "OPT_UI_DEFAULT_LOCALE", {
5242
+ enumerable: true,
5243
+ get: function() {
5244
+ return OPT_UI_DEFAULT_LOCALE;
5245
+ }
5246
+ });
4782
5247
  Object.defineProperty(exports, "Pagination", {
4783
5248
  enumerable: true,
4784
5249
  get: function() {
@@ -4845,6 +5310,36 @@ Object.defineProperty(exports, "SelectTrigger", {
4845
5310
  return SelectTrigger;
4846
5311
  }
4847
5312
  });
5313
+ Object.defineProperty(exports, "Skeleton", {
5314
+ enumerable: true,
5315
+ get: function() {
5316
+ return Skeleton;
5317
+ }
5318
+ });
5319
+ Object.defineProperty(exports, "SkeletonAvatar", {
5320
+ enumerable: true,
5321
+ get: function() {
5322
+ return SkeletonAvatar;
5323
+ }
5324
+ });
5325
+ Object.defineProperty(exports, "SkeletonCard", {
5326
+ enumerable: true,
5327
+ get: function() {
5328
+ return SkeletonCard;
5329
+ }
5330
+ });
5331
+ Object.defineProperty(exports, "SkeletonTable", {
5332
+ enumerable: true,
5333
+ get: function() {
5334
+ return SkeletonTable;
5335
+ }
5336
+ });
5337
+ Object.defineProperty(exports, "SkeletonText", {
5338
+ enumerable: true,
5339
+ get: function() {
5340
+ return SkeletonText;
5341
+ }
5342
+ });
4848
5343
  Object.defineProperty(exports, "Slider", {
4849
5344
  enumerable: true,
4850
5345
  get: function() {
@@ -4899,6 +5394,12 @@ Object.defineProperty(exports, "TagInput", {
4899
5394
  return TagInput;
4900
5395
  }
4901
5396
  });
5397
+ Object.defineProperty(exports, "TextTruncate", {
5398
+ enumerable: true,
5399
+ get: function() {
5400
+ return TextTruncate;
5401
+ }
5402
+ });
4902
5403
  Object.defineProperty(exports, "ToolbarButton", {
4903
5404
  enumerable: true,
4904
5405
  get: function() {
@@ -4965,6 +5466,30 @@ Object.defineProperty(exports, "cn", {
4965
5466
  return cn;
4966
5467
  }
4967
5468
  });
5469
+ Object.defineProperty(exports, "formatOptDateTime", {
5470
+ enumerable: true,
5471
+ get: function() {
5472
+ return formatOptDateTime;
5473
+ }
5474
+ });
5475
+ Object.defineProperty(exports, "formatOptNumber", {
5476
+ enumerable: true,
5477
+ get: function() {
5478
+ return formatOptNumber;
5479
+ }
5480
+ });
5481
+ Object.defineProperty(exports, "formatOptShortDate", {
5482
+ enumerable: true,
5483
+ get: function() {
5484
+ return formatOptShortDate;
5485
+ }
5486
+ });
5487
+ Object.defineProperty(exports, "formatOptTime", {
5488
+ enumerable: true,
5489
+ get: function() {
5490
+ return formatOptTime;
5491
+ }
5492
+ });
4968
5493
  Object.defineProperty(exports, "getDescribedBy", {
4969
5494
  enumerable: true,
4970
5495
  get: function() {