@almadar/ui 5.128.0 → 5.129.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.
package/dist/avl/index.js CHANGED
@@ -29578,12 +29578,12 @@ var init_MapView = __esm({
29578
29578
  shadowSize: [41, 41]
29579
29579
  });
29580
29580
  L.Marker.prototype.options.icon = defaultIcon;
29581
- const { useEffect: useEffect63, useRef: useRef61, useCallback: useCallback93, useState: useState97 } = React91__default;
29581
+ const { useEffect: useEffect63, useRef: useRef62, useCallback: useCallback93, useState: useState97 } = React91__default;
29582
29582
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29583
29583
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29584
29584
  function MapUpdater({ centerLat, centerLng, zoom }) {
29585
29585
  const map = useMap();
29586
- const prevRef = useRef61({ centerLat, centerLng, zoom });
29586
+ const prevRef = useRef62({ centerLat, centerLng, zoom });
29587
29587
  useEffect63(() => {
29588
29588
  const prev = prevRef.current;
29589
29589
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
@@ -38364,6 +38364,290 @@ var init_GraphCanvas = __esm({
38364
38364
  GraphCanvas.displayName = "GraphCanvas";
38365
38365
  }
38366
38366
  });
38367
+ var ImportSourcePicker;
38368
+ var init_ImportSourcePicker = __esm({
38369
+ "components/core/molecules/import/ImportSourcePicker.tsx"() {
38370
+ "use client";
38371
+ init_Box();
38372
+ init_Icon();
38373
+ init_Typography();
38374
+ init_cn();
38375
+ ImportSourcePicker = ({
38376
+ sources,
38377
+ onSelect,
38378
+ onFilesSelected,
38379
+ title,
38380
+ moreSources,
38381
+ className
38382
+ }) => {
38383
+ const fileInputRef = useRef(null);
38384
+ const handlePick = (source) => {
38385
+ if (source.disabled) return;
38386
+ if (source.kind === "file") {
38387
+ const input = fileInputRef.current;
38388
+ if (!input) return;
38389
+ input.accept = source.accept ?? "";
38390
+ input.multiple = source.multiple ?? false;
38391
+ input.click();
38392
+ return;
38393
+ }
38394
+ onSelect?.(source.id);
38395
+ };
38396
+ const handleFiles = (event) => {
38397
+ const files = event.target.files ? Array.from(event.target.files) : [];
38398
+ event.target.value = "";
38399
+ if (files.length > 0) onFilesSelected?.(files);
38400
+ };
38401
+ return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col gap-2", className), children: [
38402
+ title ? /* @__PURE__ */ jsx(Typography, { variant: "h4", children: title }) : null,
38403
+ sources.map((source) => /* @__PURE__ */ jsxs(
38404
+ Box,
38405
+ {
38406
+ role: "button",
38407
+ tabIndex: source.disabled ? -1 : 0,
38408
+ "aria-disabled": source.disabled,
38409
+ onClick: () => handlePick(source),
38410
+ onKeyDown: (event) => {
38411
+ if (event.key === "Enter" || event.key === " ") {
38412
+ event.preventDefault();
38413
+ handlePick(source);
38414
+ }
38415
+ },
38416
+ className: cn(
38417
+ "flex items-center gap-3 rounded-md border border-border bg-card px-4 py-3 text-left",
38418
+ source.disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer hover:bg-accent hover:text-accent-foreground"
38419
+ ),
38420
+ children: [
38421
+ source.icon ? /* @__PURE__ */ jsx(Icon, { icon: source.icon, size: "md" }) : null,
38422
+ /* @__PURE__ */ jsxs(Box, { className: "flex flex-col", children: [
38423
+ /* @__PURE__ */ jsx(Typography, { variant: "label", children: source.label }),
38424
+ source.description ? /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: source.description }) : null
38425
+ ] })
38426
+ ]
38427
+ },
38428
+ source.id
38429
+ )),
38430
+ moreSources,
38431
+ /* @__PURE__ */ jsx(
38432
+ "input",
38433
+ {
38434
+ ref: fileInputRef,
38435
+ type: "file",
38436
+ className: "hidden",
38437
+ onChange: handleFiles,
38438
+ "data-testid": "import-source-file-input"
38439
+ }
38440
+ )
38441
+ ] });
38442
+ };
38443
+ }
38444
+ });
38445
+ function formatFieldValue(value) {
38446
+ if (value === null) return "\u2014";
38447
+ if (value instanceof Date) return value.toISOString();
38448
+ if (Array.isArray(value)) return value.map(formatFieldValue).join(", ");
38449
+ if (typeof value === "object") return JSON.stringify(value);
38450
+ return String(value);
38451
+ }
38452
+ function unitTitle(unit) {
38453
+ for (const key of TITLE_KEYS) {
38454
+ const value = unit.fields[key];
38455
+ if (typeof value === "string" && value.length > 0) return value;
38456
+ }
38457
+ return unit.ref;
38458
+ }
38459
+ function fieldSummary(unit) {
38460
+ return Object.entries(unit.fields).filter(([key]) => !TITLE_KEYS.includes(key)).map(([key, value]) => `${key}: ${formatFieldValue(value)}`).join(" \xB7 ");
38461
+ }
38462
+ var TITLE_KEYS, ImportPreviewTree;
38463
+ var init_ImportPreviewTree = __esm({
38464
+ "components/core/molecules/import/ImportPreviewTree.tsx"() {
38465
+ "use client";
38466
+ init_Box();
38467
+ init_Badge();
38468
+ init_Button();
38469
+ init_Icon();
38470
+ init_Typography();
38471
+ init_cn();
38472
+ TITLE_KEYS = ["title", "name", "label"];
38473
+ ImportPreviewTree = ({
38474
+ units,
38475
+ skipped = [],
38476
+ entityDisplay,
38477
+ onConfirm,
38478
+ onCancel,
38479
+ confirmLabel = "Confirm import",
38480
+ cancelLabel = "Cancel",
38481
+ indent = 16,
38482
+ className
38483
+ }) => {
38484
+ const groups = /* @__PURE__ */ new Map();
38485
+ for (const unit of units) {
38486
+ const group = groups.get(unit.targetEntity);
38487
+ if (group) group.push(unit);
38488
+ else groups.set(unit.targetEntity, [unit]);
38489
+ }
38490
+ const renderUnit = (unit, childrenByParent, depth) => {
38491
+ const summary = fieldSummary(unit);
38492
+ const children = childrenByParent.get(unit.ref) ?? [];
38493
+ return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
38494
+ /* @__PURE__ */ jsxs(
38495
+ Box,
38496
+ {
38497
+ className: "flex flex-col py-1",
38498
+ style: { paddingLeft: depth * indent },
38499
+ "data-testid": `import-preview-unit-${unit.ref}`,
38500
+ children: [
38501
+ /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-2", children: [
38502
+ /* @__PURE__ */ jsx(Icon, { icon: "file-text", size: "xs", className: "text-muted-foreground" }),
38503
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", children: unitTitle(unit) })
38504
+ ] }),
38505
+ summary ? /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: summary }) : null
38506
+ ]
38507
+ }
38508
+ ),
38509
+ children.map((child) => renderUnit(child, childrenByParent, depth + 1))
38510
+ ] }, unit.ref);
38511
+ };
38512
+ return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col gap-4", className), children: [
38513
+ units.length === 0 ? /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: "No units staged." }) : null,
38514
+ Array.from(groups.entries()).map(([entity, groupUnits]) => {
38515
+ const refs = new Set(groupUnits.map((unit) => unit.ref));
38516
+ const childrenByParent = /* @__PURE__ */ new Map();
38517
+ const roots = [];
38518
+ for (const unit of groupUnits) {
38519
+ if (unit.parentRef && refs.has(unit.parentRef)) {
38520
+ const siblings = childrenByParent.get(unit.parentRef);
38521
+ if (siblings) siblings.push(unit);
38522
+ else childrenByParent.set(unit.parentRef, [unit]);
38523
+ } else {
38524
+ roots.push(unit);
38525
+ }
38526
+ }
38527
+ const label = entityDisplay[entity]?.plural ?? entity;
38528
+ return /* @__PURE__ */ jsxs(Box, { border: true, className: "rounded-md border-border bg-card p-3", children: [
38529
+ /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-2 pb-2", children: [
38530
+ /* @__PURE__ */ jsx(Typography, { variant: "label", children: label }),
38531
+ /* @__PURE__ */ jsx(Badge, { amount: groupUnits.length })
38532
+ ] }),
38533
+ roots.map((unit) => renderUnit(unit, childrenByParent, 0))
38534
+ ] }, entity);
38535
+ }),
38536
+ skipped.length > 0 ? /* @__PURE__ */ jsxs(Box, { border: true, className: "rounded-md border-border bg-card p-3", children: [
38537
+ /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-2 pb-2", children: [
38538
+ /* @__PURE__ */ jsx(Typography, { variant: "label", children: "Skipped" }),
38539
+ /* @__PURE__ */ jsx(Badge, { amount: skipped.length })
38540
+ ] }),
38541
+ skipped.map((element) => /* @__PURE__ */ jsxs(Box, { className: "flex items-baseline gap-2 py-1", children: [
38542
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", children: element.ref }),
38543
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: element.reason })
38544
+ ] }, element.ref))
38545
+ ] }) : null,
38546
+ onConfirm || onCancel ? /* @__PURE__ */ jsxs(Box, { className: "flex items-center justify-end gap-2", children: [
38547
+ onCancel ? /* @__PURE__ */ jsx(Button, { variant: "default", label: cancelLabel, onClick: onCancel }) : null,
38548
+ onConfirm ? /* @__PURE__ */ jsx(Button, { variant: "primary", label: confirmLabel, onClick: onConfirm }) : null
38549
+ ] }) : null
38550
+ ] });
38551
+ };
38552
+ }
38553
+ });
38554
+ var PIPELINE, DEFAULT_LABELS, ImportProgress;
38555
+ var init_ImportProgress = __esm({
38556
+ "components/core/molecules/import/ImportProgress.tsx"() {
38557
+ "use client";
38558
+ init_Box();
38559
+ init_Badge();
38560
+ init_Icon();
38561
+ init_Typography();
38562
+ init_cn();
38563
+ PIPELINE = [
38564
+ "fetching",
38565
+ "mapping",
38566
+ "reviewing",
38567
+ "committing"
38568
+ ];
38569
+ DEFAULT_LABELS = {
38570
+ fetching: "Fetching",
38571
+ mapping: "Mapping",
38572
+ reviewing: "Reviewing",
38573
+ committing: "Committing",
38574
+ done: "Done",
38575
+ failed: "Failed"
38576
+ };
38577
+ ImportProgress = ({
38578
+ step,
38579
+ counts,
38580
+ labels,
38581
+ className
38582
+ }) => {
38583
+ const label = (key) => labels?.[key] ?? DEFAULT_LABELS[key];
38584
+ const currentIndex = step === "done" || step === "failed" ? PIPELINE.length : PIPELINE.indexOf(step);
38585
+ return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col gap-3", className), children: [
38586
+ /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-2", children: [
38587
+ PIPELINE.map((key, index) => {
38588
+ const isComplete = index < currentIndex;
38589
+ const isActive = index === currentIndex;
38590
+ return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
38591
+ index > 0 ? /* @__PURE__ */ jsx(Box, { className: "h-px w-4 bg-border" }) : null,
38592
+ /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", "data-testid": `import-progress-step-${key}`, children: [
38593
+ /* @__PURE__ */ jsx(
38594
+ Icon,
38595
+ {
38596
+ icon: isComplete ? "check" : isActive ? "loader" : "circle",
38597
+ size: "sm",
38598
+ className: cn(
38599
+ isComplete ? "text-success" : isActive ? "text-primary" : "text-muted-foreground"
38600
+ )
38601
+ }
38602
+ ),
38603
+ /* @__PURE__ */ jsx(
38604
+ Typography,
38605
+ {
38606
+ variant: "caption",
38607
+ className: cn(isActive ? "text-foreground" : "text-muted-foreground"),
38608
+ children: label(key)
38609
+ }
38610
+ )
38611
+ ] })
38612
+ ] }, key);
38613
+ }),
38614
+ step === "done" || step === "failed" ? /* @__PURE__ */ jsxs(Fragment, { children: [
38615
+ /* @__PURE__ */ jsx(Box, { className: "h-px w-4 bg-border" }),
38616
+ /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", "data-testid": `import-progress-step-${step}`, children: [
38617
+ /* @__PURE__ */ jsx(
38618
+ Icon,
38619
+ {
38620
+ icon: step === "done" ? "check" : "x",
38621
+ size: "sm",
38622
+ className: step === "done" ? "text-success" : "text-error"
38623
+ }
38624
+ ),
38625
+ /* @__PURE__ */ jsx(
38626
+ Typography,
38627
+ {
38628
+ variant: "caption",
38629
+ className: step === "done" ? "text-success" : "text-error",
38630
+ children: label(step)
38631
+ }
38632
+ )
38633
+ ] })
38634
+ ] }) : null
38635
+ ] }),
38636
+ counts ? /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-2", children: [
38637
+ counts.staged !== void 0 ? /* @__PURE__ */ jsx(Badge, { label: `Staged ${counts.staged}` }) : null,
38638
+ counts.committed !== void 0 ? /* @__PURE__ */ jsx(Badge, { variant: "success", label: `Committed ${counts.committed}` }) : null,
38639
+ counts.failed !== void 0 ? /* @__PURE__ */ jsx(Badge, { variant: "danger", label: `Failed ${counts.failed}` }) : null
38640
+ ] }) : null
38641
+ ] });
38642
+ };
38643
+ }
38644
+ });
38645
+
38646
+ // components/core/molecules/import/index.ts
38647
+ var init_import = __esm({
38648
+ "components/core/molecules/import/index.ts"() {
38649
+ }
38650
+ });
38367
38651
  var ReflectionBlock;
38368
38652
  var init_ReflectionBlock = __esm({
38369
38653
  "components/core/molecules/ReflectionBlock.tsx"() {
@@ -38438,6 +38722,7 @@ var init_molecules2 = __esm({
38438
38722
  init_EmptyState();
38439
38723
  init_Pagination();
38440
38724
  init_molecules();
38725
+ init_import();
38441
38726
  }
38442
38727
  });
38443
38728
 
@@ -38918,7 +39203,7 @@ function getBadgeVariant(fieldName, value) {
38918
39203
  function formatFieldLabel(fieldName) {
38919
39204
  return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase());
38920
39205
  }
38921
- function formatFieldValue(value, fieldName) {
39206
+ function formatFieldValue2(value, fieldName) {
38922
39207
  if (typeof value === "number") {
38923
39208
  if (fieldName.toLowerCase().includes("progress") || fieldName.toLowerCase().includes("percent")) {
38924
39209
  return `${value}%`;
@@ -39013,7 +39298,7 @@ function renderRichFieldValue(value, fieldName, fieldType) {
39013
39298
  return str;
39014
39299
  }
39015
39300
  default:
39016
- return formatFieldValue(value, fieldName);
39301
+ return formatFieldValue2(value, fieldName);
39017
39302
  }
39018
39303
  }
39019
39304
  function normalizeFieldDefs(fields) {
@@ -39124,7 +39409,7 @@ var init_DetailPanel = __esm({
39124
39409
  const value = getNestedValue(normalizedData, field);
39125
39410
  return {
39126
39411
  label: labelFor(field),
39127
- value: formatFieldValue(value, field),
39412
+ value: formatFieldValue2(value, field),
39128
39413
  icon: getFieldIcon(field)
39129
39414
  };
39130
39415
  }
@@ -45155,6 +45440,9 @@ var init_component_registry_generated = __esm({
45155
45440
  init_HeroOrganism();
45156
45441
  init_HeroSection();
45157
45442
  init_Icon();
45443
+ init_ImportPreviewTree();
45444
+ init_ImportProgress();
45445
+ init_ImportSourcePicker();
45158
45446
  init_InfiniteScrollSentinel();
45159
45447
  init_Input();
45160
45448
  init_InputGroup();
@@ -45418,6 +45706,9 @@ var init_component_registry_generated = __esm({
45418
45706
  "HeroOrganism": HeroOrganism,
45419
45707
  "HeroSection": HeroSection,
45420
45708
  "Icon": Icon,
45709
+ "ImportPreviewTree": ImportPreviewTree,
45710
+ "ImportProgress": ImportProgress,
45711
+ "ImportSourcePicker": ImportSourcePicker,
45421
45712
  "InfiniteScrollSentinel": InfiniteScrollSentinel,
45422
45713
  "Input": Input,
45423
45714
  "InputGroup": InputGroup,