klun-ui 0.3.0 → 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.
@@ -3344,6 +3344,170 @@ var DiffViewer = react.forwardRef(function DiffViewer2({
3344
3344
  );
3345
3345
  });
3346
3346
  DiffViewer.displayName = "DiffViewer";
3347
+ var Kanban = react.forwardRef(function Kanban2({ columns = [], onMove, onCardClick, renderCard, columnFooter, columnWidth = 280, className, style, ...props }, ref) {
3348
+ const [drag, setDrag] = react.useState(null);
3349
+ const [overColumn, setOverColumn] = react.useState(null);
3350
+ const handleDrop = (column, index) => {
3351
+ if (drag && (drag.fromColumn !== column.id || index !== index)) {
3352
+ onMove?.(drag.cardId, drag.fromColumn, column.id, index);
3353
+ }
3354
+ setDrag(null);
3355
+ setOverColumn(null);
3356
+ };
3357
+ return /* @__PURE__ */ jsxRuntime.jsx(
3358
+ "div",
3359
+ {
3360
+ ref,
3361
+ className: chunkTPGAXYFU_cjs.cx("klun-kanban", className),
3362
+ style: { ...style, ["--klun-kanban-col"]: `${columnWidth}px` },
3363
+ ...props,
3364
+ children: columns.map((column) => {
3365
+ const over = overColumn === column.id && drag;
3366
+ const full = column.limit !== void 0 && column.cards.length >= column.limit;
3367
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: chunkTPGAXYFU_cjs.cx("klun-kanban__column", over && "klun-kanban__column--over"), children: [
3368
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "klun-kanban__header", children: [
3369
+ column.accent ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-kanban__dot", style: { background: column.accent } }) : null,
3370
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-kanban__title", children: column.title }),
3371
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: chunkTPGAXYFU_cjs.cx("klun-kanban__count", full && "klun-kanban__count--full"), children: [
3372
+ column.cards.length,
3373
+ column.limit !== void 0 ? ` / ${column.limit}` : ""
3374
+ ] })
3375
+ ] }),
3376
+ /* @__PURE__ */ jsxRuntime.jsxs(
3377
+ "div",
3378
+ {
3379
+ className: "klun-kanban__list",
3380
+ onDragOver: (e) => {
3381
+ if (!drag) return;
3382
+ e.preventDefault();
3383
+ setOverColumn(column.id);
3384
+ },
3385
+ onDrop: (e) => {
3386
+ e.preventDefault();
3387
+ handleDrop(column, column.cards.length);
3388
+ },
3389
+ children: [
3390
+ column.cards.map((card, index) => /* @__PURE__ */ jsxRuntime.jsx(
3391
+ "article",
3392
+ {
3393
+ draggable: true,
3394
+ onDragStart: (e) => {
3395
+ e.dataTransfer.effectAllowed = "move";
3396
+ e.dataTransfer.setData("text/plain", card.id);
3397
+ setDrag({ cardId: card.id, fromColumn: column.id });
3398
+ },
3399
+ onDragEnd: () => {
3400
+ setDrag(null);
3401
+ setOverColumn(null);
3402
+ },
3403
+ onDragOver: (e) => {
3404
+ if (!drag) return;
3405
+ e.preventDefault();
3406
+ e.stopPropagation();
3407
+ const rect = e.currentTarget.getBoundingClientRect();
3408
+ const after = e.clientY - rect.top > rect.height / 2;
3409
+ setOverColumn(column.id);
3410
+ setDrag((d) => d ? { ...d, overColumn: column.id, overIndex: index + (after ? 1 : 0) } : d);
3411
+ },
3412
+ onDrop: (e) => {
3413
+ e.preventDefault();
3414
+ e.stopPropagation();
3415
+ handleDrop(column, index);
3416
+ },
3417
+ onClick: () => onCardClick?.(card, column.id),
3418
+ className: chunkTPGAXYFU_cjs.cx(
3419
+ "klun-kanban__card",
3420
+ drag?.cardId === card.id && "klun-kanban__card--dragging",
3421
+ over && drag?.overIndex === index && "klun-kanban__card--dropbefore",
3422
+ over && drag?.overIndex === index + 1 && "klun-kanban__card--dropafter"
3423
+ ),
3424
+ style: card.accent ? { boxShadow: `inset 3px 0 0 ${card.accent}` } : void 0,
3425
+ children: renderCard ? renderCard(card, column.id) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3426
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-kanban__card-title", children: card.title }),
3427
+ card.description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-kanban__card-desc", children: card.description }) : null,
3428
+ card.tags?.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-kanban__card-tags", children: card.tags.map((t, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { children: t }, i)) }) : null,
3429
+ card.meta ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-kanban__card-meta", children: card.meta }) : null
3430
+ ] })
3431
+ },
3432
+ card.id
3433
+ )),
3434
+ column.cards.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-kanban__empty", children: "Drop a card here" }) : null
3435
+ ]
3436
+ }
3437
+ ),
3438
+ columnFooter ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-kanban__footer", children: columnFooter(column) }) : null
3439
+ ] }, column.id);
3440
+ })
3441
+ }
3442
+ );
3443
+ });
3444
+ Kanban.displayName = "Kanban";
3445
+ function VirtualTable({
3446
+ rows = [],
3447
+ columns = [],
3448
+ rowHeight = 40,
3449
+ height = 420,
3450
+ getRowId,
3451
+ onRowClick,
3452
+ overscan = 8,
3453
+ zebra = true,
3454
+ empty,
3455
+ className,
3456
+ style,
3457
+ ...props
3458
+ }) {
3459
+ const [scrollTop, setScrollTop] = react.useState(0);
3460
+ const total = rows.length;
3461
+ const template = react.useMemo(
3462
+ () => columns.map((c) => c.width ? `${c.width}px` : "minmax(0, 1fr)").join(" "),
3463
+ [columns]
3464
+ );
3465
+ const bodyHeight = Math.max(0, height - 36);
3466
+ const start = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);
3467
+ const end = Math.min(total, Math.ceil((scrollTop + bodyHeight) / rowHeight) + overscan);
3468
+ const slice = rows.slice(start, end);
3469
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: void 0, className: chunkTPGAXYFU_cjs.cx("klun-vtable", className), style: { ...style, height }, ...props, children: [
3470
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-vtable__head", style: { gridTemplateColumns: template }, children: columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkTPGAXYFU_cjs.cx("klun-vtable__th", c.align && `klun-vtable__th--${c.align}`), children: c.header }, c.key)) }),
3471
+ /* @__PURE__ */ jsxRuntime.jsx(
3472
+ "div",
3473
+ {
3474
+ className: "klun-vtable__body",
3475
+ onScroll: (e) => setScrollTop(e.target.scrollTop),
3476
+ style: { maxHeight: bodyHeight },
3477
+ children: total === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-vtable__empty", children: empty ?? "No rows" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3478
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: start * rowHeight } }),
3479
+ slice.map((row, i) => {
3480
+ const index = start + i;
3481
+ const id = getRowId?.(row, index) ?? index;
3482
+ return /* @__PURE__ */ jsxRuntime.jsx(
3483
+ "div",
3484
+ {
3485
+ role: onRowClick ? "button" : void 0,
3486
+ tabIndex: onRowClick ? 0 : void 0,
3487
+ onClick: () => onRowClick?.(row, index),
3488
+ className: chunkTPGAXYFU_cjs.cx(
3489
+ "klun-vtable__row",
3490
+ zebra && index % 2 === 1 && "klun-vtable__row--zebra",
3491
+ onRowClick && "klun-vtable__row--clickable"
3492
+ ),
3493
+ style: { gridTemplateColumns: template, height: rowHeight },
3494
+ children: columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkTPGAXYFU_cjs.cx("klun-vtable__td", c.align && `klun-vtable__td--${c.align}`), children: c.render ? c.render(row, index) : String(row[c.key] ?? "") }, c.key))
3495
+ },
3496
+ id
3497
+ );
3498
+ }),
3499
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: Math.max(0, (total - end) * rowHeight) } })
3500
+ ] })
3501
+ }
3502
+ ),
3503
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-vtable__foot", children: [
3504
+ total.toLocaleString("en-US"),
3505
+ " rows \xB7 rendering ",
3506
+ slice.length
3507
+ ] })
3508
+ ] });
3509
+ }
3510
+ VirtualTable.displayName = "VirtualTable";
3347
3511
  var Kbd = react.forwardRef(function Kbd2({ className, children, ...props }, ref) {
3348
3512
  return /* @__PURE__ */ jsxRuntime.jsx("kbd", { ref, className: chunkTPGAXYFU_cjs.cx("klun-kbd", className), ...props, children });
3349
3513
  });
@@ -7499,6 +7663,149 @@ var CompactSelectForInput = react.forwardRef(function CompactSelectForInput2({
7499
7663
  );
7500
7664
  });
7501
7665
  CompactSelectForInput.displayName = "CompactSelectForInput";
7666
+ var CRON_PRESETS = [
7667
+ { label: "Every 5 minutes", value: "*/5 * * * *" },
7668
+ { label: "Every 15 minutes", value: "*/15 * * * *" },
7669
+ { label: "Hourly", value: "0 * * * *" },
7670
+ { label: "Every day at 03:00", value: "0 3 * * *" },
7671
+ { label: "Weekdays at 09:00", value: "0 9 * * 1-5" },
7672
+ { label: "Mondays at 09:00", value: "0 9 * * 1" },
7673
+ { label: "1st of the month", value: "0 6 1 * *" }
7674
+ ];
7675
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
7676
+ var DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
7677
+ var pad = (n) => n.padStart(2, "0");
7678
+ function describeCron(cron) {
7679
+ const parts = cron.trim().split(/\s+/);
7680
+ if (parts.length !== 5) return cron;
7681
+ const [min, hour, day, month, week] = parts;
7682
+ const everyMin = min.startsWith("*/") ? `every ${min.slice(2)} minutes` : min === "*" ? "every minute" : null;
7683
+ const at = hour === "*" ? "" : ` at ${pad(hour)}:${pad(min)}`;
7684
+ const dayPart = week === "*" && day === "*" ? month === "*" ? "every day" : `on day ${day} of month ${month}` : week !== "*" ? `on ${week.split(",").map((w) => w.includes("-") ? w.split("-").map((x) => DAYS[Number(x)] ?? x).join("\u2013") : DAYS[Number(w)] ?? w).join(", ")}` : `on day ${day} of the month`;
7685
+ if (everyMin) return `${everyMin.charAt(0).toUpperCase()}${everyMin.slice(1)}${at}`;
7686
+ if (min !== "*" && hour !== "*" && day === "*" && week === "*") {
7687
+ return `${month === "*" ? "Every day" : `On day ${day} of month ${MONTHS[Number(month) - 1] ?? month}`}${at}`;
7688
+ }
7689
+ return `${dayPart.charAt(0).toUpperCase()}${dayPart.slice(1)}${at}`;
7690
+ }
7691
+ function parse(cron) {
7692
+ const p = cron.trim().split(/\s+/);
7693
+ return [p[0] ?? "*", p[1] ?? "*", p[2] ?? "*", p[3] ?? "*", p[4] ?? "*"];
7694
+ }
7695
+ var CronEditor = react.forwardRef(function CronEditor2({
7696
+ value,
7697
+ defaultValue = "0 3 * * *",
7698
+ onChange,
7699
+ hidePresets = false,
7700
+ disabled = false,
7701
+ size: sizeProp,
7702
+ labels,
7703
+ className,
7704
+ style,
7705
+ ...props
7706
+ }, ref) {
7707
+ const size = useSize(sizeProp) === "small" ? "small" : "medium";
7708
+ const text = {
7709
+ minute: "Minute",
7710
+ hour: "Hour",
7711
+ day: "Day",
7712
+ month: "Month",
7713
+ weekday: "Weekday",
7714
+ every: "Every",
7715
+ expression: "Expression",
7716
+ ...labels
7717
+ };
7718
+ const [inner, setInner] = react.useState(defaultValue);
7719
+ const current = value ?? inner;
7720
+ const [fields, setFields] = react.useState(parse(current));
7721
+ react.useEffect(() => {
7722
+ setFields(parse(current));
7723
+ }, [current]);
7724
+ const commit = (next) => {
7725
+ if (value === void 0) setInner(next);
7726
+ onChange?.(next);
7727
+ };
7728
+ const setField = (index, next) => {
7729
+ const copy = [...fields];
7730
+ copy[index] = next;
7731
+ setFields(copy);
7732
+ commit(copy.join(" "));
7733
+ };
7734
+ const options = react.useMemo(
7735
+ () => ({
7736
+ minute: ["*", "*/5", "*/10", "*/15", "*/30", "0", "15", "30", "45"],
7737
+ hour: ["*", ...Array.from({ length: 24 }, (_, i) => String(i))],
7738
+ day: ["*", ...Array.from({ length: 31 }, (_, i) => String(i + 1))],
7739
+ month: ["*", ...Array.from({ length: 12 }, (_, i) => String(i + 1))],
7740
+ weekday: ["*", "1-5", "0", "1", "2", "3", "4", "5", "6"]
7741
+ }),
7742
+ []
7743
+ );
7744
+ const fieldLabel = (key, v) => {
7745
+ if (v === "*") return text.every;
7746
+ if (key === "month") return MONTHS[Number(v) - 1] ?? v;
7747
+ if (key === "weekday") return v.includes("-") ? "Mon\u2013Fri" : DAYS[Number(v)] ?? v;
7748
+ if (key === "hour") return `${pad(v)}:00`;
7749
+ return v;
7750
+ };
7751
+ const desc = describeCron(current);
7752
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7753
+ "div",
7754
+ {
7755
+ ref,
7756
+ className: chunkTPGAXYFU_cjs.cx("klun-cron", `klun-cron--${size}`, disabled && "klun-cron--disabled", className),
7757
+ style,
7758
+ ...props,
7759
+ children: [
7760
+ !hidePresets ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-cron__presets", children: CRON_PRESETS.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
7761
+ "button",
7762
+ {
7763
+ type: "button",
7764
+ disabled,
7765
+ onClick: () => commit(p.value),
7766
+ "data-active": current === p.value || void 0,
7767
+ className: "klun-cron__preset",
7768
+ children: p.label
7769
+ },
7770
+ p.value
7771
+ )) }) : null,
7772
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-cron__fields", children: ["minute", "hour", "day", "month", "weekday"].map((key, i) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "klun-cron__field", children: [
7773
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-cron__field-label", children: text[key] }),
7774
+ /* @__PURE__ */ jsxRuntime.jsx(
7775
+ "select",
7776
+ {
7777
+ disabled,
7778
+ value: fields[i],
7779
+ onChange: (e) => setField(i, e.target.value),
7780
+ className: "klun-cron__select",
7781
+ children: options[key].map((v) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: v, children: fieldLabel(key, v) }, v))
7782
+ }
7783
+ )
7784
+ ] }, key)) }),
7785
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-cron__footer", children: [
7786
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "klun-cron__raw", children: [
7787
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "klun-cron__field-label", children: text.expression }),
7788
+ /* @__PURE__ */ jsxRuntime.jsx(
7789
+ "input",
7790
+ {
7791
+ disabled,
7792
+ value: current,
7793
+ onChange: (e) => commit(e.target.value),
7794
+ spellCheck: false,
7795
+ className: "klun-cron__input"
7796
+ }
7797
+ )
7798
+ ] }),
7799
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-cron__preview", children: [
7800
+ /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-time-line" }),
7801
+ desc
7802
+ ] })
7803
+ ] })
7804
+ ]
7805
+ }
7806
+ );
7807
+ });
7808
+ CronEditor.displayName = "CronEditor";
7502
7809
  var CounterInput = react.forwardRef(function CounterInput2({
7503
7810
  value = 0,
7504
7811
  min = -Infinity,
@@ -7928,7 +8235,7 @@ var DateRangePicker = react.forwardRef(
7928
8235
  }
7929
8236
  );
7930
8237
  DateRangePicker.displayName = "DateRangePicker";
7931
- var pad = (n) => String(n).padStart(2, "0");
8238
+ var pad2 = (n) => String(n).padStart(2, "0");
7932
8239
  var TimePicker = react.forwardRef(
7933
8240
  function TimePicker2({ value = "09:00", onChange, className, style, ...props }, ref) {
7934
8241
  const t = useLocale();
@@ -7938,7 +8245,7 @@ var TimePicker = react.forwardRef(
7938
8245
  const set = (nh, nm, nmer) => {
7939
8246
  let hh = nh % 12;
7940
8247
  if (nmer === "PM") hh += 12;
7941
- onChange?.(`${pad(hh)}:${pad(nm)}`);
8248
+ onChange?.(`${pad2(hh)}:${pad2(nm)}`);
7942
8249
  };
7943
8250
  const [open, setOpen] = react.useState(null);
7944
8251
  const rootRef = react.useRef(null);
@@ -7957,11 +8264,11 @@ var TimePicker = react.forwardRef(
7957
8264
  }, [open]);
7958
8265
  const hourOpts = Array.from({ length: 12 }, (_, i) => ({
7959
8266
  value: String(i + 1),
7960
- label: pad(i + 1)
8267
+ label: pad2(i + 1)
7961
8268
  }));
7962
8269
  const minOpts = Array.from({ length: 60 }, (_, i) => ({
7963
8270
  value: String(i),
7964
- label: pad(i)
8271
+ label: pad2(i)
7965
8272
  }));
7966
8273
  const merOpts = [
7967
8274
  { value: "AM", label: t.timePicker.am },
@@ -8128,7 +8435,7 @@ function TimeColumn({
8128
8435
  ] });
8129
8436
  }
8130
8437
  TimePicker.displayName = "TimePicker";
8131
- var pad2 = (n) => String(n).padStart(2, "0");
8438
+ var pad3 = (n) => String(n).padStart(2, "0");
8132
8439
  var DEFAULT_FORMAT3 = {
8133
8440
  year: "numeric",
8134
8441
  month: "short",
@@ -8137,7 +8444,7 @@ var DEFAULT_FORMAT3 = {
8137
8444
  minute: "2-digit"
8138
8445
  };
8139
8446
  function DateTimePanel({ value, onChange }) {
8140
- const hhmm = value ? `${pad2(value.getHours())}:${pad2(value.getMinutes())}` : "09:00";
8447
+ const hhmm = value ? `${pad3(value.getHours())}:${pad3(value.getMinutes())}` : "09:00";
8141
8448
  const setDate = (d) => {
8142
8449
  const next = new Date(d);
8143
8450
  if (value) next.setHours(value.getHours(), value.getMinutes(), 0, 0);
@@ -9120,6 +9427,192 @@ var RichEditorToolbar = react.forwardRef(
9120
9427
  }
9121
9428
  );
9122
9429
  RichEditorToolbar.displayName = "RichEditorToolbar";
9430
+ var Textarea = react.forwardRef(function Textarea2({ error = false, disabled = false, readOnly = false, size: sizeProp, rows = 4, className, style, ...props }, ref) {
9431
+ const size = useSize(sizeProp);
9432
+ return /* @__PURE__ */ jsxRuntime.jsx(
9433
+ "div",
9434
+ {
9435
+ className: chunkTPGAXYFU_cjs.cx(
9436
+ "klun-textarea",
9437
+ `klun-textarea--${size}`,
9438
+ error && "klun-textarea--error",
9439
+ disabled && "klun-textarea--disabled",
9440
+ readOnly && "klun-textarea--readonly",
9441
+ className
9442
+ ),
9443
+ style,
9444
+ children: /* @__PURE__ */ jsxRuntime.jsx(
9445
+ "textarea",
9446
+ {
9447
+ ref,
9448
+ className: "klun-textarea__field",
9449
+ rows,
9450
+ disabled,
9451
+ readOnly,
9452
+ ...props
9453
+ }
9454
+ )
9455
+ }
9456
+ );
9457
+ });
9458
+ Textarea.displayName = "Textarea";
9459
+ function runCommand(id) {
9460
+ const exec = (cmd, arg) => document.execCommand(cmd, false, arg);
9461
+ if (typeof document.execCommand !== "function") return;
9462
+ switch (id) {
9463
+ case "bold":
9464
+ case "italic":
9465
+ case "underline":
9466
+ case "strikeThrough":
9467
+ exec(id);
9468
+ break;
9469
+ case "strike":
9470
+ exec("strikeThrough");
9471
+ break;
9472
+ case "h1":
9473
+ exec("formatBlock", "<h1>");
9474
+ break;
9475
+ case "h2":
9476
+ exec("formatBlock", "<h2>");
9477
+ break;
9478
+ case "quote":
9479
+ exec("formatBlock", "<blockquote>");
9480
+ break;
9481
+ case "code":
9482
+ exec("formatBlock", "<pre>");
9483
+ break;
9484
+ case "ul":
9485
+ exec("insertUnorderedList");
9486
+ break;
9487
+ case "ol":
9488
+ exec("insertOrderedList");
9489
+ break;
9490
+ case "link": {
9491
+ const url = typeof window !== "undefined" ? window.prompt("Link URL", "https://") : null;
9492
+ if (url) exec("createLink", url);
9493
+ break;
9494
+ }
9495
+ case "image": {
9496
+ const url = typeof window !== "undefined" ? window.prompt("Image URL", "https://") : null;
9497
+ if (url) exec("insertImage", url);
9498
+ break;
9499
+ }
9500
+ }
9501
+ }
9502
+ var RichEditor = react.forwardRef(function RichEditor2({
9503
+ value,
9504
+ defaultValue = "",
9505
+ onChange,
9506
+ placeholder = "Write something\u2026",
9507
+ disabled = false,
9508
+ hideToolbar = false,
9509
+ minHeight = 160,
9510
+ maxHeight,
9511
+ allowSource = true,
9512
+ editorLabel = "Rich text editor",
9513
+ className,
9514
+ style,
9515
+ ...props
9516
+ }, ref) {
9517
+ const editorRef = react.useRef(null);
9518
+ const [active, setActive] = react.useState([]);
9519
+ const [source, setSource] = react.useState(false);
9520
+ const [html, setHtml] = react.useState(value ?? defaultValue);
9521
+ react.useEffect(() => {
9522
+ const el = editorRef.current;
9523
+ if (!el) return;
9524
+ const next = value ?? html;
9525
+ if (document.activeElement !== el && el.innerHTML !== next) el.innerHTML = next;
9526
+ }, [value]);
9527
+ react.useEffect(() => {
9528
+ if (disabled || typeof document.execCommand !== "function") return;
9529
+ document.execCommand("defaultParagraphSeparator", false, "p");
9530
+ }, [disabled]);
9531
+ const emit2 = () => {
9532
+ const next = editorRef.current?.innerHTML ?? "";
9533
+ setHtml(next);
9534
+ onChange?.(next);
9535
+ };
9536
+ const syncActive = () => {
9537
+ if (typeof document.queryCommandState !== "function") return;
9538
+ const next = [];
9539
+ ["bold", "italic", "underline"].forEach((c) => {
9540
+ if (document.queryCommandState(c)) next.push(c);
9541
+ });
9542
+ setActive(next);
9543
+ };
9544
+ const onAction = (id) => {
9545
+ if (disabled) return;
9546
+ editorRef.current?.focus();
9547
+ runCommand(id);
9548
+ emit2();
9549
+ syncActive();
9550
+ };
9551
+ const setRefs = (node) => {
9552
+ editorRef.current = node;
9553
+ if (typeof ref === "function") ref(node);
9554
+ else if (ref) ref.current = node;
9555
+ };
9556
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9557
+ "div",
9558
+ {
9559
+ className: chunkTPGAXYFU_cjs.cx("klun-rich-editor", disabled && "klun-rich-editor--disabled", className),
9560
+ style,
9561
+ ...props,
9562
+ children: [
9563
+ !hideToolbar ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "klun-rich-editor__bar", children: [
9564
+ /* @__PURE__ */ jsxRuntime.jsx(RichEditorToolbar, { active, onAction }),
9565
+ allowSource ? /* @__PURE__ */ jsxRuntime.jsxs(
9566
+ "button",
9567
+ {
9568
+ type: "button",
9569
+ className: "klun-rich-editor__source",
9570
+ onClick: () => setSource((s) => !s),
9571
+ "data-active": source || void 0,
9572
+ "aria-pressed": source,
9573
+ children: [
9574
+ /* @__PURE__ */ jsxRuntime.jsx("i", { className: "ri-code-s-slash-line" }),
9575
+ "HTML"
9576
+ ]
9577
+ }
9578
+ ) : null
9579
+ ] }) : null,
9580
+ source && allowSource ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "klun-rich-editor__sourcearea", children: /* @__PURE__ */ jsxRuntime.jsx(
9581
+ Textarea,
9582
+ {
9583
+ rows: Math.max(4, Math.round(minHeight / 22)),
9584
+ value: html,
9585
+ style: { border: "none", boxShadow: "none", fontFamily: "var(--klun-font-mono, monospace)" },
9586
+ onChange: (e) => {
9587
+ setHtml(e.target.value);
9588
+ onChange?.(e.target.value);
9589
+ if (editorRef.current) editorRef.current.innerHTML = e.target.value;
9590
+ }
9591
+ }
9592
+ ) }) : null,
9593
+ /* @__PURE__ */ jsxRuntime.jsx(
9594
+ "div",
9595
+ {
9596
+ ref: setRefs,
9597
+ role: "textbox",
9598
+ "aria-multiline": "true",
9599
+ "aria-label": editorLabel,
9600
+ contentEditable: !disabled,
9601
+ suppressContentEditableWarning: true,
9602
+ "data-placeholder": placeholder,
9603
+ className: "klun-rich-editor__area",
9604
+ style: { minHeight, maxHeight, overflowY: maxHeight ? "auto" : void 0 },
9605
+ onInput: emit2,
9606
+ onBlur: emit2,
9607
+ onKeyUp: syncActive,
9608
+ onMouseUp: syncActive
9609
+ }
9610
+ )
9611
+ ]
9612
+ }
9613
+ );
9614
+ });
9615
+ RichEditor.displayName = "RichEditor";
9123
9616
  var Select = react.forwardRef(function Select2({
9124
9617
  size: sizeProp,
9125
9618
  placeholder,
@@ -9399,35 +9892,6 @@ var Switch = react.forwardRef(function Switch2({ disabled = false, size: sizePro
9399
9892
  );
9400
9893
  });
9401
9894
  Switch.displayName = "Switch";
9402
- var Textarea = react.forwardRef(function Textarea2({ error = false, disabled = false, readOnly = false, size: sizeProp, rows = 4, className, style, ...props }, ref) {
9403
- const size = useSize(sizeProp);
9404
- return /* @__PURE__ */ jsxRuntime.jsx(
9405
- "div",
9406
- {
9407
- className: chunkTPGAXYFU_cjs.cx(
9408
- "klun-textarea",
9409
- `klun-textarea--${size}`,
9410
- error && "klun-textarea--error",
9411
- disabled && "klun-textarea--disabled",
9412
- readOnly && "klun-textarea--readonly",
9413
- className
9414
- ),
9415
- style,
9416
- children: /* @__PURE__ */ jsxRuntime.jsx(
9417
- "textarea",
9418
- {
9419
- ref,
9420
- className: "klun-textarea__field",
9421
- rows,
9422
- disabled,
9423
- readOnly,
9424
- ...props
9425
- }
9426
- )
9427
- }
9428
- );
9429
- });
9430
- Textarea.displayName = "Textarea";
9431
9895
  var Card = react.forwardRef(function Card2({ variant = "stroke", padding, className, style, children, ...props }, ref) {
9432
9896
  return /* @__PURE__ */ jsxRuntime.jsx(
9433
9897
  "div",
@@ -11641,6 +12105,7 @@ exports.BulkAction = BulkAction;
11641
12105
  exports.BulkActionBar = BulkActionBar;
11642
12106
  exports.Button = Button;
11643
12107
  exports.ButtonGroup = ButtonGroup;
12108
+ exports.CRON_PRESETS = CRON_PRESETS;
11644
12109
  exports.Card = Card;
11645
12110
  exports.Carousel = Carousel;
11646
12111
  exports.Cascader = Cascader;
@@ -11667,6 +12132,7 @@ exports.ContentLabel = ContentLabel;
11667
12132
  exports.ContextMenu = ContextMenu2;
11668
12133
  exports.CopyButton = CopyButton;
11669
12134
  exports.CounterInput = CounterInput;
12135
+ exports.CronEditor = CronEditor;
11670
12136
  exports.CrossRefBadge = CrossRefBadge;
11671
12137
  exports.DatePicker = DatePicker;
11672
12138
  exports.DateRangePicker = DateRangePicker;
@@ -11694,6 +12160,7 @@ exports.ImageViewer = ImageViewer;
11694
12160
  exports.InlineInput = InlineInput;
11695
12161
  exports.InlineSelect = InlineSelect;
11696
12162
  exports.Input = Input;
12163
+ exports.Kanban = Kanban;
11697
12164
  exports.Kbd = Kbd;
11698
12165
  exports.KeyIcon = KeyIcon;
11699
12166
  exports.Label = Label;
@@ -11725,6 +12192,7 @@ exports.RangeSlider = RangeSlider;
11725
12192
  exports.Rating = Rating;
11726
12193
  exports.RelativeTime = RelativeTime;
11727
12194
  exports.Result = Result;
12195
+ exports.RichEditor = RichEditor;
11728
12196
  exports.RichEditorToolbar = RichEditorToolbar;
11729
12197
  exports.Row = Row;
11730
12198
  exports.SegmentedControl = SegmentedControl;
@@ -11753,9 +12221,11 @@ exports.Toast = Toast;
11753
12221
  exports.Toaster = Toaster;
11754
12222
  exports.Tooltip = Tooltip;
11755
12223
  exports.Tree = Tree;
12224
+ exports.VirtualTable = VirtualTable;
11756
12225
  exports.Wizard = Wizard;
11757
12226
  exports.arSA = arSA;
11758
12227
  exports.deDE = deDE;
12228
+ exports.describeCron = describeCron;
11759
12229
  exports.enUS = enUS;
11760
12230
  exports.esES = esES;
11761
12231
  exports.fmt = fmt;
@@ -11786,5 +12256,5 @@ exports.useSize = useSize;
11786
12256
  exports.viVN = viVN;
11787
12257
  exports.zhCN = zhCN;
11788
12258
  exports.zhTW = zhTW;
11789
- //# sourceMappingURL=chunk-YSCRS555.cjs.map
11790
- //# sourceMappingURL=chunk-YSCRS555.cjs.map
12259
+ //# sourceMappingURL=chunk-XLK6BYW3.cjs.map
12260
+ //# sourceMappingURL=chunk-XLK6BYW3.cjs.map