@almadar/ui 5.127.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.
@@ -21622,7 +21622,7 @@ var init_DashboardLayout = __esm({
21622
21622
  ]
21623
21623
  }
21624
21624
  ),
21625
- user && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative", children: [
21625
+ user?.name && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative", children: [
21626
21626
  /* @__PURE__ */ jsxRuntime.jsxs(
21627
21627
  Button,
21628
21628
  {
@@ -26878,12 +26878,12 @@ var init_MapView = __esm({
26878
26878
  shadowSize: [41, 41]
26879
26879
  });
26880
26880
  L.Marker.prototype.options.icon = defaultIcon;
26881
- const { useEffect: useEffect59, useRef: useRef59, useCallback: useCallback87, useState: useState89 } = React82__namespace.default;
26881
+ const { useEffect: useEffect59, useRef: useRef60, useCallback: useCallback87, useState: useState89 } = React82__namespace.default;
26882
26882
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
26883
26883
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
26884
26884
  function MapUpdater({ centerLat, centerLng, zoom }) {
26885
26885
  const map = useMap();
26886
- const prevRef = useRef59({ centerLat, centerLng, zoom });
26886
+ const prevRef = useRef60({ centerLat, centerLng, zoom });
26887
26887
  useEffect59(() => {
26888
26888
  const prev = prevRef.current;
26889
26889
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
@@ -35935,6 +35935,290 @@ var init_GraphCanvas = __esm({
35935
35935
  GraphCanvas.displayName = "GraphCanvas";
35936
35936
  }
35937
35937
  });
35938
+ var ImportSourcePicker;
35939
+ var init_ImportSourcePicker = __esm({
35940
+ "components/core/molecules/import/ImportSourcePicker.tsx"() {
35941
+ "use client";
35942
+ init_Box();
35943
+ init_Icon();
35944
+ init_Typography();
35945
+ init_cn();
35946
+ ImportSourcePicker = ({
35947
+ sources,
35948
+ onSelect,
35949
+ onFilesSelected,
35950
+ title,
35951
+ moreSources,
35952
+ className
35953
+ }) => {
35954
+ const fileInputRef = React82.useRef(null);
35955
+ const handlePick = (source) => {
35956
+ if (source.disabled) return;
35957
+ if (source.kind === "file") {
35958
+ const input = fileInputRef.current;
35959
+ if (!input) return;
35960
+ input.accept = source.accept ?? "";
35961
+ input.multiple = source.multiple ?? false;
35962
+ input.click();
35963
+ return;
35964
+ }
35965
+ onSelect?.(source.id);
35966
+ };
35967
+ const handleFiles = (event) => {
35968
+ const files = event.target.files ? Array.from(event.target.files) : [];
35969
+ event.target.value = "";
35970
+ if (files.length > 0) onFilesSelected?.(files);
35971
+ };
35972
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex flex-col gap-2", className), children: [
35973
+ title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", children: title }) : null,
35974
+ sources.map((source) => /* @__PURE__ */ jsxRuntime.jsxs(
35975
+ Box,
35976
+ {
35977
+ role: "button",
35978
+ tabIndex: source.disabled ? -1 : 0,
35979
+ "aria-disabled": source.disabled,
35980
+ onClick: () => handlePick(source),
35981
+ onKeyDown: (event) => {
35982
+ if (event.key === "Enter" || event.key === " ") {
35983
+ event.preventDefault();
35984
+ handlePick(source);
35985
+ }
35986
+ },
35987
+ className: cn(
35988
+ "flex items-center gap-3 rounded-md border border-border bg-card px-4 py-3 text-left",
35989
+ source.disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer hover:bg-accent hover:text-accent-foreground"
35990
+ ),
35991
+ children: [
35992
+ source.icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: source.icon, size: "md" }) : null,
35993
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col", children: [
35994
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "label", children: source.label }),
35995
+ source.description ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: source.description }) : null
35996
+ ] })
35997
+ ]
35998
+ },
35999
+ source.id
36000
+ )),
36001
+ moreSources,
36002
+ /* @__PURE__ */ jsxRuntime.jsx(
36003
+ "input",
36004
+ {
36005
+ ref: fileInputRef,
36006
+ type: "file",
36007
+ className: "hidden",
36008
+ onChange: handleFiles,
36009
+ "data-testid": "import-source-file-input"
36010
+ }
36011
+ )
36012
+ ] });
36013
+ };
36014
+ }
36015
+ });
36016
+ function formatFieldValue(value) {
36017
+ if (value === null) return "\u2014";
36018
+ if (value instanceof Date) return value.toISOString();
36019
+ if (Array.isArray(value)) return value.map(formatFieldValue).join(", ");
36020
+ if (typeof value === "object") return JSON.stringify(value);
36021
+ return String(value);
36022
+ }
36023
+ function unitTitle(unit) {
36024
+ for (const key of TITLE_KEYS) {
36025
+ const value = unit.fields[key];
36026
+ if (typeof value === "string" && value.length > 0) return value;
36027
+ }
36028
+ return unit.ref;
36029
+ }
36030
+ function fieldSummary(unit) {
36031
+ return Object.entries(unit.fields).filter(([key]) => !TITLE_KEYS.includes(key)).map(([key, value]) => `${key}: ${formatFieldValue(value)}`).join(" \xB7 ");
36032
+ }
36033
+ var TITLE_KEYS, ImportPreviewTree;
36034
+ var init_ImportPreviewTree = __esm({
36035
+ "components/core/molecules/import/ImportPreviewTree.tsx"() {
36036
+ "use client";
36037
+ init_Box();
36038
+ init_Badge();
36039
+ init_Button();
36040
+ init_Icon();
36041
+ init_Typography();
36042
+ init_cn();
36043
+ TITLE_KEYS = ["title", "name", "label"];
36044
+ ImportPreviewTree = ({
36045
+ units,
36046
+ skipped = [],
36047
+ entityDisplay,
36048
+ onConfirm,
36049
+ onCancel,
36050
+ confirmLabel = "Confirm import",
36051
+ cancelLabel = "Cancel",
36052
+ indent = 16,
36053
+ className
36054
+ }) => {
36055
+ const groups = /* @__PURE__ */ new Map();
36056
+ for (const unit of units) {
36057
+ const group = groups.get(unit.targetEntity);
36058
+ if (group) group.push(unit);
36059
+ else groups.set(unit.targetEntity, [unit]);
36060
+ }
36061
+ const renderUnit = (unit, childrenByParent, depth) => {
36062
+ const summary = fieldSummary(unit);
36063
+ const children = childrenByParent.get(unit.ref) ?? [];
36064
+ return /* @__PURE__ */ jsxRuntime.jsxs(React82__namespace.default.Fragment, { children: [
36065
+ /* @__PURE__ */ jsxRuntime.jsxs(
36066
+ Box,
36067
+ {
36068
+ className: "flex flex-col py-1",
36069
+ style: { paddingLeft: depth * indent },
36070
+ "data-testid": `import-preview-unit-${unit.ref}`,
36071
+ children: [
36072
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center gap-2", children: [
36073
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: "file-text", size: "xs", className: "text-muted-foreground" }),
36074
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", children: unitTitle(unit) })
36075
+ ] }),
36076
+ summary ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: summary }) : null
36077
+ ]
36078
+ }
36079
+ ),
36080
+ children.map((child) => renderUnit(child, childrenByParent, depth + 1))
36081
+ ] }, unit.ref);
36082
+ };
36083
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex flex-col gap-4", className), children: [
36084
+ units.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: "No units staged." }) : null,
36085
+ Array.from(groups.entries()).map(([entity, groupUnits]) => {
36086
+ const refs = new Set(groupUnits.map((unit) => unit.ref));
36087
+ const childrenByParent = /* @__PURE__ */ new Map();
36088
+ const roots = [];
36089
+ for (const unit of groupUnits) {
36090
+ if (unit.parentRef && refs.has(unit.parentRef)) {
36091
+ const siblings = childrenByParent.get(unit.parentRef);
36092
+ if (siblings) siblings.push(unit);
36093
+ else childrenByParent.set(unit.parentRef, [unit]);
36094
+ } else {
36095
+ roots.push(unit);
36096
+ }
36097
+ }
36098
+ const label = entityDisplay[entity]?.plural ?? entity;
36099
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { border: true, className: "rounded-md border-border bg-card p-3", children: [
36100
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center gap-2 pb-2", children: [
36101
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "label", children: label }),
36102
+ /* @__PURE__ */ jsxRuntime.jsx(Badge, { amount: groupUnits.length })
36103
+ ] }),
36104
+ roots.map((unit) => renderUnit(unit, childrenByParent, 0))
36105
+ ] }, entity);
36106
+ }),
36107
+ skipped.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(Box, { border: true, className: "rounded-md border-border bg-card p-3", children: [
36108
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center gap-2 pb-2", children: [
36109
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "label", children: "Skipped" }),
36110
+ /* @__PURE__ */ jsxRuntime.jsx(Badge, { amount: skipped.length })
36111
+ ] }),
36112
+ skipped.map((element) => /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-baseline gap-2 py-1", children: [
36113
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", children: element.ref }),
36114
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: element.reason })
36115
+ ] }, element.ref))
36116
+ ] }) : null,
36117
+ onConfirm || onCancel ? /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center justify-end gap-2", children: [
36118
+ onCancel ? /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "default", label: cancelLabel, onClick: onCancel }) : null,
36119
+ onConfirm ? /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "primary", label: confirmLabel, onClick: onConfirm }) : null
36120
+ ] }) : null
36121
+ ] });
36122
+ };
36123
+ }
36124
+ });
36125
+ var PIPELINE, DEFAULT_LABELS, ImportProgress;
36126
+ var init_ImportProgress = __esm({
36127
+ "components/core/molecules/import/ImportProgress.tsx"() {
36128
+ "use client";
36129
+ init_Box();
36130
+ init_Badge();
36131
+ init_Icon();
36132
+ init_Typography();
36133
+ init_cn();
36134
+ PIPELINE = [
36135
+ "fetching",
36136
+ "mapping",
36137
+ "reviewing",
36138
+ "committing"
36139
+ ];
36140
+ DEFAULT_LABELS = {
36141
+ fetching: "Fetching",
36142
+ mapping: "Mapping",
36143
+ reviewing: "Reviewing",
36144
+ committing: "Committing",
36145
+ done: "Done",
36146
+ failed: "Failed"
36147
+ };
36148
+ ImportProgress = ({
36149
+ step,
36150
+ counts,
36151
+ labels,
36152
+ className
36153
+ }) => {
36154
+ const label = (key) => labels?.[key] ?? DEFAULT_LABELS[key];
36155
+ const currentIndex = step === "done" || step === "failed" ? PIPELINE.length : PIPELINE.indexOf(step);
36156
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex flex-col gap-3", className), children: [
36157
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center gap-2", children: [
36158
+ PIPELINE.map((key, index) => {
36159
+ const isComplete = index < currentIndex;
36160
+ const isActive = index === currentIndex;
36161
+ return /* @__PURE__ */ jsxRuntime.jsxs(React82__namespace.default.Fragment, { children: [
36162
+ index > 0 ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "h-px w-4 bg-border" }) : null,
36163
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center gap-1", "data-testid": `import-progress-step-${key}`, children: [
36164
+ /* @__PURE__ */ jsxRuntime.jsx(
36165
+ Icon,
36166
+ {
36167
+ icon: isComplete ? "check" : isActive ? "loader" : "circle",
36168
+ size: "sm",
36169
+ className: cn(
36170
+ isComplete ? "text-success" : isActive ? "text-primary" : "text-muted-foreground"
36171
+ )
36172
+ }
36173
+ ),
36174
+ /* @__PURE__ */ jsxRuntime.jsx(
36175
+ Typography,
36176
+ {
36177
+ variant: "caption",
36178
+ className: cn(isActive ? "text-foreground" : "text-muted-foreground"),
36179
+ children: label(key)
36180
+ }
36181
+ )
36182
+ ] })
36183
+ ] }, key);
36184
+ }),
36185
+ step === "done" || step === "failed" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
36186
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "h-px w-4 bg-border" }),
36187
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center gap-1", "data-testid": `import-progress-step-${step}`, children: [
36188
+ /* @__PURE__ */ jsxRuntime.jsx(
36189
+ Icon,
36190
+ {
36191
+ icon: step === "done" ? "check" : "x",
36192
+ size: "sm",
36193
+ className: step === "done" ? "text-success" : "text-error"
36194
+ }
36195
+ ),
36196
+ /* @__PURE__ */ jsxRuntime.jsx(
36197
+ Typography,
36198
+ {
36199
+ variant: "caption",
36200
+ className: step === "done" ? "text-success" : "text-error",
36201
+ children: label(step)
36202
+ }
36203
+ )
36204
+ ] })
36205
+ ] }) : null
36206
+ ] }),
36207
+ counts ? /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center gap-2", children: [
36208
+ counts.staged !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { label: `Staged ${counts.staged}` }) : null,
36209
+ counts.committed !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "success", label: `Committed ${counts.committed}` }) : null,
36210
+ counts.failed !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "danger", label: `Failed ${counts.failed}` }) : null
36211
+ ] }) : null
36212
+ ] });
36213
+ };
36214
+ }
36215
+ });
36216
+
36217
+ // components/core/molecules/import/index.ts
36218
+ var init_import = __esm({
36219
+ "components/core/molecules/import/index.ts"() {
36220
+ }
36221
+ });
35938
36222
  var ReflectionBlock;
35939
36223
  var init_ReflectionBlock = __esm({
35940
36224
  "components/core/molecules/ReflectionBlock.tsx"() {
@@ -36009,6 +36293,7 @@ var init_molecules2 = __esm({
36009
36293
  init_EmptyState();
36010
36294
  init_Pagination();
36011
36295
  init_molecules();
36296
+ init_import();
36012
36297
  }
36013
36298
  });
36014
36299
 
@@ -36489,7 +36774,7 @@ function getBadgeVariant(fieldName, value) {
36489
36774
  function formatFieldLabel(fieldName) {
36490
36775
  return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase());
36491
36776
  }
36492
- function formatFieldValue(value, fieldName) {
36777
+ function formatFieldValue2(value, fieldName) {
36493
36778
  if (typeof value === "number") {
36494
36779
  if (fieldName.toLowerCase().includes("progress") || fieldName.toLowerCase().includes("percent")) {
36495
36780
  return `${value}%`;
@@ -36584,7 +36869,7 @@ function renderRichFieldValue(value, fieldName, fieldType) {
36584
36869
  return str;
36585
36870
  }
36586
36871
  default:
36587
- return formatFieldValue(value, fieldName);
36872
+ return formatFieldValue2(value, fieldName);
36588
36873
  }
36589
36874
  }
36590
36875
  function normalizeFieldDefs(fields) {
@@ -36695,7 +36980,7 @@ var init_DetailPanel = __esm({
36695
36980
  const value = getNestedValue(normalizedData, field);
36696
36981
  return {
36697
36982
  label: labelFor(field),
36698
- value: formatFieldValue(value, field),
36983
+ value: formatFieldValue2(value, field),
36699
36984
  icon: getFieldIcon(field)
36700
36985
  };
36701
36986
  }
@@ -42726,6 +43011,9 @@ var init_component_registry_generated = __esm({
42726
43011
  init_HeroOrganism();
42727
43012
  init_HeroSection();
42728
43013
  init_Icon();
43014
+ init_ImportPreviewTree();
43015
+ init_ImportProgress();
43016
+ init_ImportSourcePicker();
42729
43017
  init_InfiniteScrollSentinel();
42730
43018
  init_Input();
42731
43019
  init_InputGroup();
@@ -42989,6 +43277,9 @@ var init_component_registry_generated = __esm({
42989
43277
  "HeroOrganism": HeroOrganism,
42990
43278
  "HeroSection": HeroSection,
42991
43279
  "Icon": Icon,
43280
+ "ImportPreviewTree": ImportPreviewTree,
43281
+ "ImportProgress": ImportProgress,
43282
+ "ImportSourcePicker": ImportSourcePicker,
42992
43283
  "InfiniteScrollSentinel": InfiniteScrollSentinel,
42993
43284
  "Input": Input,
42994
43285
  "InputGroup": InputGroup,