@almadar/ui 5.29.0 → 5.30.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.cjs +265 -6305
- package/dist/avl/index.js +266 -6306
- package/dist/components/core/molecules/DocumentViewer.d.ts +0 -2
- package/dist/components/core/molecules/Header.d.ts +0 -4
- package/dist/components/core/molecules/Navigation.d.ts +0 -2
- package/dist/components/core/molecules/PageHeader.d.ts +0 -2
- package/dist/components/core/molecules/PropertyInspector.d.ts +8 -1
- package/dist/components/game/molecules/three/index.cjs +27 -2
- package/dist/components/game/molecules/three/index.js +27 -2
- package/dist/components/game/organisms/TraitSlot.d.ts +3 -1
- package/dist/components/game/organisms/types/isometric.d.ts +2 -0
- package/dist/components/index.cjs +773 -680
- package/dist/components/index.js +775 -682
- package/dist/providers/index.cjs +165 -101
- package/dist/providers/index.js +165 -101
- package/dist/renderer/pattern-resolver.d.ts +2 -5
- package/dist/runtime/index.cjs +165 -101
- package/dist/runtime/index.js +165 -101
- package/package.json +1 -1
package/dist/components/index.js
CHANGED
|
@@ -45,7 +45,7 @@ import { useSortable, arrayMove, sortableKeyboardCoordinates, SortableContext, r
|
|
|
45
45
|
import { CSS } from '@dnd-kit/utilities';
|
|
46
46
|
import { useNodeId, ReactFlowProvider, Handle, Position } from '@xyflow/react';
|
|
47
47
|
import { useUISlots } from '@almadar/ui/context';
|
|
48
|
-
import { getPatternDefinition, getComponentForPattern as getComponentForPattern$1 } from '@almadar/patterns';
|
|
48
|
+
import { getPatternDefinition as getPatternDefinition$1, getComponentForPattern as getComponentForPattern$1 } from '@almadar/patterns';
|
|
49
49
|
import { context, Canvas } from '@react-three/fiber';
|
|
50
50
|
|
|
51
51
|
var __defProp = Object.defineProperty;
|
|
@@ -7081,11 +7081,15 @@ var init_Skeleton = __esm({
|
|
|
7081
7081
|
function getKnownPatterns() {
|
|
7082
7082
|
return Object.keys(componentMapping);
|
|
7083
7083
|
}
|
|
7084
|
-
|
|
7084
|
+
function getPatternDefinition(type) {
|
|
7085
|
+
return patternRegistry[type];
|
|
7086
|
+
}
|
|
7087
|
+
var componentMapping, patternRegistry;
|
|
7085
7088
|
var init_pattern_resolver = __esm({
|
|
7086
7089
|
"renderer/pattern-resolver.ts"() {
|
|
7087
7090
|
createLogger("almadar:ui:pattern-resolver");
|
|
7088
7091
|
componentMapping = {};
|
|
7092
|
+
patternRegistry = {};
|
|
7089
7093
|
}
|
|
7090
7094
|
});
|
|
7091
7095
|
|
|
@@ -20710,7 +20714,84 @@ var init_DashboardLayout = __esm({
|
|
|
20710
20714
|
NavLinkBottom.displayName = "NavLinkBottom";
|
|
20711
20715
|
}
|
|
20712
20716
|
});
|
|
20713
|
-
|
|
20717
|
+
function computeMenuStyle(position, triggerRect) {
|
|
20718
|
+
const isTop = position.startsWith("top");
|
|
20719
|
+
const isRight = position.endsWith("right") || position.endsWith("end");
|
|
20720
|
+
if (isTop) {
|
|
20721
|
+
return {
|
|
20722
|
+
top: triggerRect.top - MENU_GAP,
|
|
20723
|
+
transform: "translateY(-100%)",
|
|
20724
|
+
...isRight ? { right: window.innerWidth - triggerRect.right } : { left: triggerRect.left }
|
|
20725
|
+
};
|
|
20726
|
+
}
|
|
20727
|
+
return {
|
|
20728
|
+
top: triggerRect.bottom + MENU_GAP,
|
|
20729
|
+
...isRight ? { right: window.innerWidth - triggerRect.right } : { left: triggerRect.left }
|
|
20730
|
+
};
|
|
20731
|
+
}
|
|
20732
|
+
function SubMenu({
|
|
20733
|
+
items,
|
|
20734
|
+
itemRef,
|
|
20735
|
+
direction,
|
|
20736
|
+
eventBus
|
|
20737
|
+
}) {
|
|
20738
|
+
const [rect, setRect] = useState(null);
|
|
20739
|
+
useEffect(() => {
|
|
20740
|
+
if (itemRef) {
|
|
20741
|
+
setRect(itemRef.getBoundingClientRect());
|
|
20742
|
+
}
|
|
20743
|
+
}, [itemRef]);
|
|
20744
|
+
if (!rect) return null;
|
|
20745
|
+
const isRtl = direction === "rtl";
|
|
20746
|
+
const style = {
|
|
20747
|
+
top: rect.top,
|
|
20748
|
+
...isRtl ? { right: window.innerWidth - rect.left } : { left: rect.right }
|
|
20749
|
+
};
|
|
20750
|
+
const panel = /* @__PURE__ */ jsx(
|
|
20751
|
+
"div",
|
|
20752
|
+
{
|
|
20753
|
+
className: cn("fixed z-50", menuContainerStyles),
|
|
20754
|
+
style,
|
|
20755
|
+
children: items.map((item, index) => {
|
|
20756
|
+
const isDivider = item.id === "divider" || item.label === "divider";
|
|
20757
|
+
const itemId = item.id ?? `item-${item.label.toLowerCase().replace(/\s+/g, "-")}-${index}`;
|
|
20758
|
+
const isDanger = item.variant === "danger";
|
|
20759
|
+
if (isDivider) {
|
|
20760
|
+
return /* @__PURE__ */ jsx(Divider, { className: "my-1" }, `divider-${index}`);
|
|
20761
|
+
}
|
|
20762
|
+
return /* @__PURE__ */ jsxs(
|
|
20763
|
+
Box,
|
|
20764
|
+
{
|
|
20765
|
+
as: "button",
|
|
20766
|
+
onClick: () => {
|
|
20767
|
+
if (item.disabled) return;
|
|
20768
|
+
if (item.event) eventBus.emit(`UI:${item.event}`, { itemId, label: item.label });
|
|
20769
|
+
item.onClick?.();
|
|
20770
|
+
},
|
|
20771
|
+
"aria-disabled": item.disabled || void 0,
|
|
20772
|
+
"data-testid": item.event ? `action-${item.event}` : void 0,
|
|
20773
|
+
className: cn(
|
|
20774
|
+
"w-full flex items-center gap-3 px-4 py-2 text-start",
|
|
20775
|
+
"text-sm transition-colors",
|
|
20776
|
+
"hover:bg-muted focus:outline-none focus:bg-muted",
|
|
20777
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
20778
|
+
item.disabled && "cursor-not-allowed",
|
|
20779
|
+
isDanger && "text-error hover:bg-error/10"
|
|
20780
|
+
),
|
|
20781
|
+
children: [
|
|
20782
|
+
item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm", className: "flex-shrink-0" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm", className: "flex-shrink-0" })),
|
|
20783
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", className: cn("flex-1", isDanger && "text-red-600"), children: item.label }),
|
|
20784
|
+
item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs font-medium", children: item.badge })
|
|
20785
|
+
]
|
|
20786
|
+
},
|
|
20787
|
+
itemId
|
|
20788
|
+
);
|
|
20789
|
+
})
|
|
20790
|
+
}
|
|
20791
|
+
);
|
|
20792
|
+
return typeof document !== "undefined" ? createPortal(panel, document.body) : panel;
|
|
20793
|
+
}
|
|
20794
|
+
var MENU_GAP, menuContainerStyles, Menu;
|
|
20714
20795
|
var init_Menu = __esm({
|
|
20715
20796
|
"components/core/molecules/Menu.tsx"() {
|
|
20716
20797
|
"use client";
|
|
@@ -20721,6 +20802,14 @@ var init_Menu = __esm({
|
|
|
20721
20802
|
init_Badge();
|
|
20722
20803
|
init_cn();
|
|
20723
20804
|
init_useEventBus();
|
|
20805
|
+
MENU_GAP = 4;
|
|
20806
|
+
menuContainerStyles = cn(
|
|
20807
|
+
"bg-card",
|
|
20808
|
+
"border-[length:var(--border-width)] border-border",
|
|
20809
|
+
"shadow-elevation-popover",
|
|
20810
|
+
"rounded-sm",
|
|
20811
|
+
"min-w-0 sm:min-w-[200px] max-w-[calc(100vw-1rem)] py-1"
|
|
20812
|
+
);
|
|
20724
20813
|
Menu = ({
|
|
20725
20814
|
trigger,
|
|
20726
20815
|
items,
|
|
@@ -20728,9 +20817,10 @@ var init_Menu = __esm({
|
|
|
20728
20817
|
className
|
|
20729
20818
|
}) => {
|
|
20730
20819
|
const eventBus = useEventBus();
|
|
20731
|
-
const {
|
|
20820
|
+
const { direction } = useTranslate();
|
|
20732
20821
|
const [isOpen, setIsOpen] = useState(false);
|
|
20733
20822
|
const [activeSubMenu, setActiveSubMenu] = useState(null);
|
|
20823
|
+
const [activeSubMenuRef, setActiveSubMenuRef] = useState(null);
|
|
20734
20824
|
const [triggerRect, setTriggerRect] = useState(null);
|
|
20735
20825
|
const triggerRef = useRef(null);
|
|
20736
20826
|
const menuRef = useRef(null);
|
|
@@ -20745,13 +20835,14 @@ var init_Menu = __esm({
|
|
|
20745
20835
|
}
|
|
20746
20836
|
setIsOpen(!isOpen);
|
|
20747
20837
|
setActiveSubMenu(null);
|
|
20838
|
+
setActiveSubMenuRef(null);
|
|
20748
20839
|
};
|
|
20749
|
-
const handleItemClick = (item) => {
|
|
20840
|
+
const handleItemClick = (item, itemId) => {
|
|
20750
20841
|
if (item.disabled) return;
|
|
20751
20842
|
if (item.subMenu && item.subMenu.length > 0) {
|
|
20752
|
-
setActiveSubMenu(
|
|
20843
|
+
setActiveSubMenu(itemId);
|
|
20753
20844
|
} else {
|
|
20754
|
-
if (item.event) eventBus.emit(`UI:${item.event}`, { itemId
|
|
20845
|
+
if (item.event) eventBus.emit(`UI:${item.event}`, { itemId, label: item.label });
|
|
20755
20846
|
item.onClick?.();
|
|
20756
20847
|
setIsOpen(false);
|
|
20757
20848
|
}
|
|
@@ -20766,22 +20857,12 @@ var init_Menu = __esm({
|
|
|
20766
20857
|
if (isOpen && menuRef.current && !menuRef.current.contains(e.target) && triggerRef.current && !triggerRef.current.contains(e.target)) {
|
|
20767
20858
|
setIsOpen(false);
|
|
20768
20859
|
setActiveSubMenu(null);
|
|
20860
|
+
setActiveSubMenuRef(null);
|
|
20769
20861
|
}
|
|
20770
20862
|
};
|
|
20771
20863
|
document.addEventListener("mousedown", handleClickOutside);
|
|
20772
20864
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
20773
20865
|
}, [isOpen]);
|
|
20774
|
-
const positionClasses = {
|
|
20775
|
-
"top-left": "bottom-full left-0 mb-2",
|
|
20776
|
-
"top-right": "bottom-full right-0 mb-2",
|
|
20777
|
-
"bottom-left": "top-full left-0 mt-2",
|
|
20778
|
-
"bottom-right": "top-full right-0 mt-2",
|
|
20779
|
-
// Aliases for pattern compatibility
|
|
20780
|
-
"top-start": "bottom-full left-0 mb-2",
|
|
20781
|
-
"top-end": "bottom-full right-0 mb-2",
|
|
20782
|
-
"bottom-start": "top-full left-0 mt-2",
|
|
20783
|
-
"bottom-end": "top-full right-0 mt-2"
|
|
20784
|
-
};
|
|
20785
20866
|
const rtlMirror = {
|
|
20786
20867
|
"top-left": "top-right",
|
|
20787
20868
|
"top-right": "top-left",
|
|
@@ -20793,7 +20874,6 @@ var init_Menu = __esm({
|
|
|
20793
20874
|
"bottom-end": "bottom-start"
|
|
20794
20875
|
};
|
|
20795
20876
|
const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
|
|
20796
|
-
const subMenuSideClass = direction === "rtl" ? "right-full mr-2" : "left-full ml-2";
|
|
20797
20877
|
const triggerChild = React74__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
|
|
20798
20878
|
const triggerElement = React74__default.cloneElement(
|
|
20799
20879
|
triggerChild,
|
|
@@ -20802,94 +20882,83 @@ var init_Menu = __esm({
|
|
|
20802
20882
|
onClick: handleToggle
|
|
20803
20883
|
}
|
|
20804
20884
|
);
|
|
20805
|
-
const
|
|
20806
|
-
"
|
|
20807
|
-
"border-[length:var(--border-width)] border-border",
|
|
20808
|
-
"shadow-elevation-popover",
|
|
20809
|
-
"rounded-sm",
|
|
20810
|
-
"min-w-0 sm:min-w-[200px] max-w-[calc(100vw-1rem)] py-1"
|
|
20811
|
-
);
|
|
20812
|
-
const renderMenuItem = (item, hasSubMenu, index) => {
|
|
20885
|
+
const renderMenuItems = (menuItems) => menuItems.map((item, index) => {
|
|
20886
|
+
const isDivider = item.id === "divider" || item.label === "divider";
|
|
20813
20887
|
const itemId = item.id ?? `item-${item.label.toLowerCase().replace(/\s+/g, "-")}-${index}`;
|
|
20888
|
+
const hasSubMenu = !!(item.subMenu && item.subMenu.length > 0);
|
|
20814
20889
|
const isDanger = item.variant === "danger";
|
|
20815
|
-
|
|
20816
|
-
|
|
20817
|
-
|
|
20818
|
-
|
|
20819
|
-
|
|
20820
|
-
|
|
20821
|
-
|
|
20822
|
-
|
|
20823
|
-
|
|
20824
|
-
"
|
|
20825
|
-
|
|
20826
|
-
|
|
20827
|
-
|
|
20828
|
-
|
|
20829
|
-
item.disabled && "cursor-not-allowed",
|
|
20830
|
-
isDanger && "text-error hover:bg-error/10"
|
|
20831
|
-
),
|
|
20832
|
-
children: /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-3 flex-1 min-w-0", children: [
|
|
20833
|
-
item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm", className: "flex-shrink-0" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm", className: "flex-shrink-0" })),
|
|
20834
|
-
/* @__PURE__ */ jsx(
|
|
20835
|
-
Typography,
|
|
20836
|
-
{
|
|
20837
|
-
variant: "small",
|
|
20838
|
-
className: cn("flex-1", isDanger && "text-red-600"),
|
|
20839
|
-
children: item.label
|
|
20890
|
+
if (isDivider) {
|
|
20891
|
+
return /* @__PURE__ */ jsx(Divider, { className: "my-1" }, `divider-${index}`);
|
|
20892
|
+
}
|
|
20893
|
+
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
20894
|
+
/* @__PURE__ */ jsx(
|
|
20895
|
+
Box,
|
|
20896
|
+
{
|
|
20897
|
+
as: "button",
|
|
20898
|
+
onClick: () => handleItemClick({ ...item, id: itemId }, itemId),
|
|
20899
|
+
"aria-disabled": item.disabled || void 0,
|
|
20900
|
+
onMouseEnter: (e) => {
|
|
20901
|
+
if (hasSubMenu) {
|
|
20902
|
+
setActiveSubMenu(itemId);
|
|
20903
|
+
setActiveSubMenuRef(e.currentTarget);
|
|
20840
20904
|
}
|
|
20905
|
+
},
|
|
20906
|
+
"data-testid": item.event ? `action-${item.event}` : void 0,
|
|
20907
|
+
className: cn(
|
|
20908
|
+
"w-full flex items-center justify-between gap-3 px-4 py-2 text-start",
|
|
20909
|
+
"text-sm transition-colors",
|
|
20910
|
+
"hover:bg-muted",
|
|
20911
|
+
"focus:outline-none focus:bg-muted",
|
|
20912
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
20913
|
+
item.disabled && "cursor-not-allowed",
|
|
20914
|
+
isDanger && "text-error hover:bg-error/10"
|
|
20841
20915
|
),
|
|
20842
|
-
|
|
20843
|
-
|
|
20844
|
-
|
|
20845
|
-
|
|
20846
|
-
|
|
20847
|
-
|
|
20848
|
-
|
|
20849
|
-
|
|
20850
|
-
|
|
20851
|
-
const hasSubMenu = item.subMenu && item.subMenu.length > 0;
|
|
20852
|
-
const isDivider = item.id === "divider" || item.label === "divider";
|
|
20853
|
-
const itemId = item.id ?? `item-${item.label.toLowerCase().replace(/\s+/g, "-")}-${index}`;
|
|
20854
|
-
if (isDivider) {
|
|
20855
|
-
return /* @__PURE__ */ jsx(Divider, { className: "my-1" }, `divider-${index}`);
|
|
20856
|
-
}
|
|
20857
|
-
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
20858
|
-
renderMenuItem(item, !!hasSubMenu, index),
|
|
20859
|
-
hasSubMenu && activeSubMenu === itemId && item.subMenu && /* @__PURE__ */ jsx(
|
|
20860
|
-
Box,
|
|
20861
|
-
{
|
|
20862
|
-
className: cn(
|
|
20863
|
-
"absolute top-0 z-50",
|
|
20864
|
-
subMenuSideClass,
|
|
20865
|
-
menuContainerStyles
|
|
20916
|
+
children: /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-3 flex-1 min-w-0", children: [
|
|
20917
|
+
item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm", className: "flex-shrink-0" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm", className: "flex-shrink-0" })),
|
|
20918
|
+
/* @__PURE__ */ jsx(
|
|
20919
|
+
Typography,
|
|
20920
|
+
{
|
|
20921
|
+
variant: "small",
|
|
20922
|
+
className: cn("flex-1", isDanger && "text-red-600"),
|
|
20923
|
+
children: item.label
|
|
20924
|
+
}
|
|
20866
20925
|
),
|
|
20867
|
-
children:
|
|
20868
|
-
|
|
20869
|
-
|
|
20870
|
-
|
|
20871
|
-
|
|
20872
|
-
|
|
20873
|
-
|
|
20926
|
+
item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge }),
|
|
20927
|
+
hasSubMenu && /* @__PURE__ */ jsx(
|
|
20928
|
+
Icon,
|
|
20929
|
+
{
|
|
20930
|
+
name: direction === "rtl" ? "chevron-left" : "chevron-right",
|
|
20931
|
+
size: "sm",
|
|
20932
|
+
className: "flex-shrink-0"
|
|
20933
|
+
}
|
|
20934
|
+
)
|
|
20935
|
+
] })
|
|
20936
|
+
}
|
|
20937
|
+
),
|
|
20938
|
+
hasSubMenu && activeSubMenu === itemId && item.subMenu && /* @__PURE__ */ jsx(
|
|
20939
|
+
SubMenu,
|
|
20940
|
+
{
|
|
20941
|
+
items: item.subMenu,
|
|
20942
|
+
itemRef: activeSubMenuRef,
|
|
20943
|
+
direction,
|
|
20944
|
+
eventBus
|
|
20945
|
+
}
|
|
20946
|
+
)
|
|
20947
|
+
] }, itemId);
|
|
20948
|
+
});
|
|
20949
|
+
const panel = isOpen && triggerRect ? /* @__PURE__ */ jsx(
|
|
20950
|
+
"div",
|
|
20951
|
+
{
|
|
20952
|
+
ref: menuRef,
|
|
20953
|
+
className: cn("fixed z-50", menuContainerStyles, className),
|
|
20954
|
+
style: computeMenuStyle(effectivePosition, triggerRect),
|
|
20955
|
+
role: "menu",
|
|
20956
|
+
children: renderMenuItems(items)
|
|
20957
|
+
}
|
|
20958
|
+
) : null;
|
|
20959
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
20874
20960
|
triggerElement,
|
|
20875
|
-
|
|
20876
|
-
Box,
|
|
20877
|
-
{
|
|
20878
|
-
ref: menuRef,
|
|
20879
|
-
className: cn(
|
|
20880
|
-
"absolute z-50",
|
|
20881
|
-
menuContainerStyles,
|
|
20882
|
-
positionClasses[effectivePosition],
|
|
20883
|
-
className
|
|
20884
|
-
),
|
|
20885
|
-
style: {
|
|
20886
|
-
left: effectivePosition.includes("left") ? 0 : "auto",
|
|
20887
|
-
right: effectivePosition.includes("right") ? 0 : "auto"
|
|
20888
|
-
},
|
|
20889
|
-
role: "menu",
|
|
20890
|
-
children: renderMenuItems(items)
|
|
20891
|
-
}
|
|
20892
|
-
)
|
|
20961
|
+
panel && typeof document !== "undefined" ? createPortal(panel, document.body) : panel
|
|
20893
20962
|
] });
|
|
20894
20963
|
};
|
|
20895
20964
|
Menu.displayName = "Menu";
|
|
@@ -22476,6 +22545,583 @@ var init_JsonTreeEditor = __esm({
|
|
|
22476
22545
|
};
|
|
22477
22546
|
}
|
|
22478
22547
|
});
|
|
22548
|
+
var FormSection, FormLayout, FormActions;
|
|
22549
|
+
var init_FormSection = __esm({
|
|
22550
|
+
"components/core/molecules/FormSection.tsx"() {
|
|
22551
|
+
"use client";
|
|
22552
|
+
init_cn();
|
|
22553
|
+
init_atoms2();
|
|
22554
|
+
init_Box();
|
|
22555
|
+
init_Typography();
|
|
22556
|
+
init_Button();
|
|
22557
|
+
init_Stack();
|
|
22558
|
+
init_Icon();
|
|
22559
|
+
init_useEventBus();
|
|
22560
|
+
FormSection = ({
|
|
22561
|
+
title,
|
|
22562
|
+
description,
|
|
22563
|
+
children,
|
|
22564
|
+
collapsible = false,
|
|
22565
|
+
defaultCollapsed = false,
|
|
22566
|
+
card = false,
|
|
22567
|
+
columns = 1,
|
|
22568
|
+
className
|
|
22569
|
+
}) => {
|
|
22570
|
+
const [collapsed, setCollapsed] = React74__default.useState(defaultCollapsed);
|
|
22571
|
+
const { t } = useTranslate();
|
|
22572
|
+
const eventBus = useEventBus();
|
|
22573
|
+
const gridClass = {
|
|
22574
|
+
1: "grid-cols-1",
|
|
22575
|
+
2: "grid-cols-1 md:grid-cols-2",
|
|
22576
|
+
3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
|
|
22577
|
+
}[columns];
|
|
22578
|
+
React74__default.useCallback(() => {
|
|
22579
|
+
if (collapsible) {
|
|
22580
|
+
setCollapsed((prev) => !prev);
|
|
22581
|
+
eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
|
|
22582
|
+
}
|
|
22583
|
+
}, [collapsible, collapsed, eventBus]);
|
|
22584
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
22585
|
+
(title || description) && /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "mb-4", children: [
|
|
22586
|
+
title && /* @__PURE__ */ jsxs(
|
|
22587
|
+
HStack,
|
|
22588
|
+
{
|
|
22589
|
+
justify: "between",
|
|
22590
|
+
align: "center",
|
|
22591
|
+
className: cn(collapsible && "cursor-pointer"),
|
|
22592
|
+
action: collapsible ? "TOGGLE_COLLAPSE" : void 0,
|
|
22593
|
+
children: [
|
|
22594
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "semibold", children: title }),
|
|
22595
|
+
collapsible && /* @__PURE__ */ jsx(
|
|
22596
|
+
Button,
|
|
22597
|
+
{
|
|
22598
|
+
variant: "ghost",
|
|
22599
|
+
size: "sm",
|
|
22600
|
+
action: "TOGGLE_COLLAPSE",
|
|
22601
|
+
children: /* @__PURE__ */ jsx(
|
|
22602
|
+
Icon,
|
|
22603
|
+
{
|
|
22604
|
+
icon: ChevronDown,
|
|
22605
|
+
size: "sm",
|
|
22606
|
+
className: cn(
|
|
22607
|
+
"text-muted-foreground transition-transform",
|
|
22608
|
+
collapsed && "rotate-180"
|
|
22609
|
+
)
|
|
22610
|
+
}
|
|
22611
|
+
)
|
|
22612
|
+
}
|
|
22613
|
+
)
|
|
22614
|
+
]
|
|
22615
|
+
}
|
|
22616
|
+
),
|
|
22617
|
+
description && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: description })
|
|
22618
|
+
] }),
|
|
22619
|
+
(!collapsible || !collapsed) && /* @__PURE__ */ jsx(Box, { className: cn("grid gap-4", gridClass), children })
|
|
22620
|
+
] });
|
|
22621
|
+
if (card) {
|
|
22622
|
+
return /* @__PURE__ */ jsx(Card, { className: cn("p-6", className), children: content });
|
|
22623
|
+
}
|
|
22624
|
+
return /* @__PURE__ */ jsx(Box, { className, children: content });
|
|
22625
|
+
};
|
|
22626
|
+
FormSection.displayName = "FormSection";
|
|
22627
|
+
FormLayout = ({
|
|
22628
|
+
children,
|
|
22629
|
+
dividers = true,
|
|
22630
|
+
className
|
|
22631
|
+
}) => {
|
|
22632
|
+
return /* @__PURE__ */ jsx(
|
|
22633
|
+
VStack,
|
|
22634
|
+
{
|
|
22635
|
+
gap: "lg",
|
|
22636
|
+
className: cn(
|
|
22637
|
+
dividers && "[&>*+*]:pt-8 [&>*+*]:border-t [&>*+*]:border-border",
|
|
22638
|
+
className
|
|
22639
|
+
),
|
|
22640
|
+
children
|
|
22641
|
+
}
|
|
22642
|
+
);
|
|
22643
|
+
};
|
|
22644
|
+
FormLayout.displayName = "FormLayout";
|
|
22645
|
+
FormActions = ({
|
|
22646
|
+
children,
|
|
22647
|
+
sticky = false,
|
|
22648
|
+
align = "right",
|
|
22649
|
+
className
|
|
22650
|
+
}) => {
|
|
22651
|
+
const alignClass2 = {
|
|
22652
|
+
left: "justify-start",
|
|
22653
|
+
right: "justify-end",
|
|
22654
|
+
between: "justify-between",
|
|
22655
|
+
center: "justify-center"
|
|
22656
|
+
}[align];
|
|
22657
|
+
return /* @__PURE__ */ jsx(
|
|
22658
|
+
HStack,
|
|
22659
|
+
{
|
|
22660
|
+
gap: "sm",
|
|
22661
|
+
align: "center",
|
|
22662
|
+
className: cn(
|
|
22663
|
+
"pt-6 border-t border-border",
|
|
22664
|
+
alignClass2,
|
|
22665
|
+
sticky && "sticky bottom-0 bg-card py-4 -mx-6 px-6 shadow-[0_-4px_6px_-1px_rgb(0,0,0,0.05)]",
|
|
22666
|
+
className
|
|
22667
|
+
),
|
|
22668
|
+
children
|
|
22669
|
+
}
|
|
22670
|
+
);
|
|
22671
|
+
};
|
|
22672
|
+
FormActions.displayName = "FormActions";
|
|
22673
|
+
}
|
|
22674
|
+
});
|
|
22675
|
+
var ALL_CATEGORY, GridPicker;
|
|
22676
|
+
var init_GridPicker = __esm({
|
|
22677
|
+
"components/core/molecules/GridPicker.tsx"() {
|
|
22678
|
+
"use client";
|
|
22679
|
+
init_cn();
|
|
22680
|
+
init_Input();
|
|
22681
|
+
init_Badge();
|
|
22682
|
+
init_Stack();
|
|
22683
|
+
ALL_CATEGORY = "__all__";
|
|
22684
|
+
GridPicker = ({
|
|
22685
|
+
items,
|
|
22686
|
+
value,
|
|
22687
|
+
onChange,
|
|
22688
|
+
categories,
|
|
22689
|
+
searchPlaceholder,
|
|
22690
|
+
renderThumbnail,
|
|
22691
|
+
cellSize = 32,
|
|
22692
|
+
className
|
|
22693
|
+
}) => {
|
|
22694
|
+
const [search, setSearch] = useState("");
|
|
22695
|
+
const [activeCategory, setActiveCategory] = useState(ALL_CATEGORY);
|
|
22696
|
+
const gridRef = useRef(null);
|
|
22697
|
+
const categoryChips = useMemo(() => {
|
|
22698
|
+
if (categories !== void 0) return categories;
|
|
22699
|
+
const seen = [];
|
|
22700
|
+
for (const item of items) {
|
|
22701
|
+
if (!seen.includes(item.category)) seen.push(item.category);
|
|
22702
|
+
}
|
|
22703
|
+
return seen;
|
|
22704
|
+
}, [categories, items]);
|
|
22705
|
+
const filtered = useMemo(() => {
|
|
22706
|
+
const needle = search.trim().toLowerCase();
|
|
22707
|
+
return items.filter((item) => {
|
|
22708
|
+
const matchesCategory = activeCategory === ALL_CATEGORY || item.category === activeCategory;
|
|
22709
|
+
const matchesSearch = needle === "" || item.label.toLowerCase().includes(needle);
|
|
22710
|
+
return matchesCategory && matchesSearch;
|
|
22711
|
+
});
|
|
22712
|
+
}, [items, search, activeCategory]);
|
|
22713
|
+
const select = useCallback(
|
|
22714
|
+
(item) => {
|
|
22715
|
+
onChange(item.id);
|
|
22716
|
+
},
|
|
22717
|
+
[onChange]
|
|
22718
|
+
);
|
|
22719
|
+
const handleKeyDown = useCallback(
|
|
22720
|
+
(e, index) => {
|
|
22721
|
+
const cells = gridRef.current?.querySelectorAll(
|
|
22722
|
+
"[data-gridpicker-cell]"
|
|
22723
|
+
);
|
|
22724
|
+
if (cells === void 0 || cells.length === 0) return;
|
|
22725
|
+
const columns = (() => {
|
|
22726
|
+
const grid = gridRef.current;
|
|
22727
|
+
if (grid === null) return 1;
|
|
22728
|
+
const style = window.getComputedStyle(grid);
|
|
22729
|
+
const cols = style.gridTemplateColumns.split(" ").filter(Boolean).length;
|
|
22730
|
+
return cols > 0 ? cols : 1;
|
|
22731
|
+
})();
|
|
22732
|
+
let next = -1;
|
|
22733
|
+
if (e.key === "ArrowRight") next = index + 1;
|
|
22734
|
+
else if (e.key === "ArrowLeft") next = index - 1;
|
|
22735
|
+
else if (e.key === "ArrowDown") next = index + columns;
|
|
22736
|
+
else if (e.key === "ArrowUp") next = index - columns;
|
|
22737
|
+
else if (e.key === "Enter" || e.key === " ") {
|
|
22738
|
+
e.preventDefault();
|
|
22739
|
+
select(filtered[index]);
|
|
22740
|
+
return;
|
|
22741
|
+
} else {
|
|
22742
|
+
return;
|
|
22743
|
+
}
|
|
22744
|
+
e.preventDefault();
|
|
22745
|
+
if (next >= 0 && next < cells.length) {
|
|
22746
|
+
cells[next].focus();
|
|
22747
|
+
}
|
|
22748
|
+
},
|
|
22749
|
+
[filtered, select]
|
|
22750
|
+
);
|
|
22751
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("w-full", className), children: [
|
|
22752
|
+
/* @__PURE__ */ jsx(
|
|
22753
|
+
Input,
|
|
22754
|
+
{
|
|
22755
|
+
type: "search",
|
|
22756
|
+
icon: "search",
|
|
22757
|
+
value: search,
|
|
22758
|
+
placeholder: searchPlaceholder,
|
|
22759
|
+
clearable: true,
|
|
22760
|
+
onClear: () => setSearch(""),
|
|
22761
|
+
onChange: (e) => setSearch(e.target.value)
|
|
22762
|
+
}
|
|
22763
|
+
),
|
|
22764
|
+
categoryChips.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", wrap: true, children: [
|
|
22765
|
+
/* @__PURE__ */ jsx(
|
|
22766
|
+
Badge,
|
|
22767
|
+
{
|
|
22768
|
+
variant: activeCategory === ALL_CATEGORY ? "primary" : "neutral",
|
|
22769
|
+
size: "sm",
|
|
22770
|
+
role: "button",
|
|
22771
|
+
tabIndex: 0,
|
|
22772
|
+
"aria-pressed": activeCategory === ALL_CATEGORY,
|
|
22773
|
+
className: "cursor-pointer",
|
|
22774
|
+
onClick: () => setActiveCategory(ALL_CATEGORY),
|
|
22775
|
+
onKeyDown: (e) => {
|
|
22776
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
22777
|
+
e.preventDefault();
|
|
22778
|
+
setActiveCategory(ALL_CATEGORY);
|
|
22779
|
+
}
|
|
22780
|
+
},
|
|
22781
|
+
children: "All"
|
|
22782
|
+
}
|
|
22783
|
+
),
|
|
22784
|
+
categoryChips.map((category) => /* @__PURE__ */ jsx(
|
|
22785
|
+
Badge,
|
|
22786
|
+
{
|
|
22787
|
+
variant: activeCategory === category ? "primary" : "neutral",
|
|
22788
|
+
size: "sm",
|
|
22789
|
+
role: "button",
|
|
22790
|
+
tabIndex: 0,
|
|
22791
|
+
"aria-pressed": activeCategory === category,
|
|
22792
|
+
className: "cursor-pointer",
|
|
22793
|
+
onClick: () => setActiveCategory(category),
|
|
22794
|
+
onKeyDown: (e) => {
|
|
22795
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
22796
|
+
e.preventDefault();
|
|
22797
|
+
setActiveCategory(category);
|
|
22798
|
+
}
|
|
22799
|
+
},
|
|
22800
|
+
children: category
|
|
22801
|
+
},
|
|
22802
|
+
category
|
|
22803
|
+
))
|
|
22804
|
+
] }),
|
|
22805
|
+
/* @__PURE__ */ jsx(
|
|
22806
|
+
"div",
|
|
22807
|
+
{
|
|
22808
|
+
ref: gridRef,
|
|
22809
|
+
role: "listbox",
|
|
22810
|
+
className: "grid gap-1 overflow-y-auto max-h-64 p-1",
|
|
22811
|
+
style: {
|
|
22812
|
+
gridTemplateColumns: `repeat(auto-fill, minmax(${cellSize}px, 1fr))`
|
|
22813
|
+
},
|
|
22814
|
+
children: filtered.map((item, index) => {
|
|
22815
|
+
const selected = item.id === value;
|
|
22816
|
+
return /* @__PURE__ */ jsx(
|
|
22817
|
+
"button",
|
|
22818
|
+
{
|
|
22819
|
+
type: "button",
|
|
22820
|
+
role: "option",
|
|
22821
|
+
"aria-selected": selected,
|
|
22822
|
+
"aria-label": item.label,
|
|
22823
|
+
title: item.label,
|
|
22824
|
+
"data-gridpicker-cell": true,
|
|
22825
|
+
tabIndex: selected || value === void 0 && index === 0 ? 0 : -1,
|
|
22826
|
+
onClick: () => select(item),
|
|
22827
|
+
onKeyDown: (e) => handleKeyDown(e, index),
|
|
22828
|
+
className: cn(
|
|
22829
|
+
"flex items-center justify-center rounded-sm",
|
|
22830
|
+
"transition-colors hover:bg-muted",
|
|
22831
|
+
"focus:outline-none focus:ring-1 focus:ring-ring",
|
|
22832
|
+
selected && "bg-primary/10 ring-1 ring-primary"
|
|
22833
|
+
),
|
|
22834
|
+
style: { width: cellSize, height: cellSize },
|
|
22835
|
+
children: renderThumbnail(item)
|
|
22836
|
+
},
|
|
22837
|
+
item.id
|
|
22838
|
+
);
|
|
22839
|
+
})
|
|
22840
|
+
}
|
|
22841
|
+
)
|
|
22842
|
+
] });
|
|
22843
|
+
};
|
|
22844
|
+
GridPicker.displayName = "GridPicker";
|
|
22845
|
+
}
|
|
22846
|
+
});
|
|
22847
|
+
function pascalToKebab(name) {
|
|
22848
|
+
return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
22849
|
+
}
|
|
22850
|
+
function kebabToPascal3(name) {
|
|
22851
|
+
return name.split("-").map((part) => /^\d+$/.test(part) ? part : part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
22852
|
+
}
|
|
22853
|
+
var ICON_ITEMS, IconPicker;
|
|
22854
|
+
var init_IconPicker = __esm({
|
|
22855
|
+
"components/core/molecules/IconPicker.tsx"() {
|
|
22856
|
+
"use client";
|
|
22857
|
+
init_Icon();
|
|
22858
|
+
init_GridPicker();
|
|
22859
|
+
ICON_ITEMS = (() => {
|
|
22860
|
+
const items = [];
|
|
22861
|
+
for (const [exportName, candidate] of Object.entries(LucideIcons2)) {
|
|
22862
|
+
if (!/^[A-Z]/.test(exportName)) continue;
|
|
22863
|
+
if (exportName.endsWith("Icon")) continue;
|
|
22864
|
+
if (exportName.startsWith("Lucide")) continue;
|
|
22865
|
+
const isComponent = candidate !== null && (typeof candidate === "object" || typeof candidate === "function") && "$$typeof" in candidate;
|
|
22866
|
+
if (!isComponent) continue;
|
|
22867
|
+
const kebab = pascalToKebab(exportName);
|
|
22868
|
+
if (kebabToPascal3(kebab) !== exportName) continue;
|
|
22869
|
+
items.push({ id: kebab, label: kebab, category: "icons" });
|
|
22870
|
+
}
|
|
22871
|
+
return items;
|
|
22872
|
+
})();
|
|
22873
|
+
IconPicker = ({ value, onChange, className }) => {
|
|
22874
|
+
const items = useMemo(() => ICON_ITEMS, []);
|
|
22875
|
+
return /* @__PURE__ */ jsx(
|
|
22876
|
+
GridPicker,
|
|
22877
|
+
{
|
|
22878
|
+
items,
|
|
22879
|
+
value,
|
|
22880
|
+
onChange,
|
|
22881
|
+
searchPlaceholder: "Search icons\u2026",
|
|
22882
|
+
renderThumbnail: (it) => /* @__PURE__ */ jsx(Icon, { name: it.id }),
|
|
22883
|
+
cellSize: 32,
|
|
22884
|
+
className
|
|
22885
|
+
}
|
|
22886
|
+
);
|
|
22887
|
+
};
|
|
22888
|
+
IconPicker.displayName = "IconPicker";
|
|
22889
|
+
}
|
|
22890
|
+
});
|
|
22891
|
+
function iconForKind(kind) {
|
|
22892
|
+
if (kind === "audio") return "music";
|
|
22893
|
+
if (kind === "model") return "box";
|
|
22894
|
+
return "file";
|
|
22895
|
+
}
|
|
22896
|
+
var THUMB_PX, IMAGE_KINDS, AssetPicker;
|
|
22897
|
+
var init_AssetPicker = __esm({
|
|
22898
|
+
"components/core/molecules/AssetPicker.tsx"() {
|
|
22899
|
+
"use client";
|
|
22900
|
+
init_GridPicker();
|
|
22901
|
+
init_Icon();
|
|
22902
|
+
THUMB_PX = 32;
|
|
22903
|
+
IMAGE_KINDS = /* @__PURE__ */ new Set([
|
|
22904
|
+
"image",
|
|
22905
|
+
"spritesheet",
|
|
22906
|
+
"scene",
|
|
22907
|
+
"portrait"
|
|
22908
|
+
]);
|
|
22909
|
+
AssetPicker = ({
|
|
22910
|
+
assets,
|
|
22911
|
+
value,
|
|
22912
|
+
onChange,
|
|
22913
|
+
className
|
|
22914
|
+
}) => {
|
|
22915
|
+
const byUrl = useMemo(() => {
|
|
22916
|
+
const map = /* @__PURE__ */ new Map();
|
|
22917
|
+
for (const entry of assets) map.set(entry.url, entry);
|
|
22918
|
+
return map;
|
|
22919
|
+
}, [assets]);
|
|
22920
|
+
const items = useMemo(
|
|
22921
|
+
() => assets.map((entry) => ({
|
|
22922
|
+
id: entry.url,
|
|
22923
|
+
label: entry.name,
|
|
22924
|
+
category: entry.category
|
|
22925
|
+
})),
|
|
22926
|
+
[assets]
|
|
22927
|
+
);
|
|
22928
|
+
const categories = useMemo(() => {
|
|
22929
|
+
const seen = [];
|
|
22930
|
+
for (const entry of assets) {
|
|
22931
|
+
if (!seen.includes(entry.category)) seen.push(entry.category);
|
|
22932
|
+
}
|
|
22933
|
+
return seen;
|
|
22934
|
+
}, [assets]);
|
|
22935
|
+
const renderThumbnail = useCallback(
|
|
22936
|
+
(item) => {
|
|
22937
|
+
const entry = byUrl.get(item.id);
|
|
22938
|
+
if (entry === void 0) return null;
|
|
22939
|
+
if (IMAGE_KINDS.has(entry.kind)) {
|
|
22940
|
+
return /* @__PURE__ */ jsx(
|
|
22941
|
+
"img",
|
|
22942
|
+
{
|
|
22943
|
+
src: entry.thumbnailUrl ?? entry.url,
|
|
22944
|
+
alt: entry.name,
|
|
22945
|
+
loading: "lazy",
|
|
22946
|
+
width: THUMB_PX,
|
|
22947
|
+
height: THUMB_PX,
|
|
22948
|
+
style: { width: THUMB_PX, height: THUMB_PX, objectFit: "cover" }
|
|
22949
|
+
}
|
|
22950
|
+
);
|
|
22951
|
+
}
|
|
22952
|
+
return /* @__PURE__ */ jsx(Icon, { name: iconForKind(entry.kind), size: "sm" });
|
|
22953
|
+
},
|
|
22954
|
+
[byUrl]
|
|
22955
|
+
);
|
|
22956
|
+
return /* @__PURE__ */ jsx(
|
|
22957
|
+
GridPicker,
|
|
22958
|
+
{
|
|
22959
|
+
items,
|
|
22960
|
+
value,
|
|
22961
|
+
onChange,
|
|
22962
|
+
categories,
|
|
22963
|
+
renderThumbnail,
|
|
22964
|
+
cellSize: THUMB_PX,
|
|
22965
|
+
className
|
|
22966
|
+
}
|
|
22967
|
+
);
|
|
22968
|
+
};
|
|
22969
|
+
AssetPicker.displayName = "AssetPicker";
|
|
22970
|
+
}
|
|
22971
|
+
});
|
|
22972
|
+
function currentValue(decl, override) {
|
|
22973
|
+
return override !== void 0 ? override : decl.default;
|
|
22974
|
+
}
|
|
22975
|
+
function TextLikeControl({
|
|
22976
|
+
field,
|
|
22977
|
+
numeric,
|
|
22978
|
+
value,
|
|
22979
|
+
onCommit
|
|
22980
|
+
}) {
|
|
22981
|
+
const initial = value === void 0 || value === null ? "" : String(value);
|
|
22982
|
+
const [draft, setDraft] = React74__default.useState(initial);
|
|
22983
|
+
React74__default.useEffect(() => setDraft(initial), [initial]);
|
|
22984
|
+
const commit = () => {
|
|
22985
|
+
if (numeric) {
|
|
22986
|
+
const n = draft.trim() === "" ? 0 : Number(draft);
|
|
22987
|
+
onCommit(field, Number.isNaN(n) ? 0 : n);
|
|
22988
|
+
} else {
|
|
22989
|
+
onCommit(field, draft);
|
|
22990
|
+
}
|
|
22991
|
+
};
|
|
22992
|
+
return /* @__PURE__ */ jsx(
|
|
22993
|
+
Input,
|
|
22994
|
+
{
|
|
22995
|
+
inputType: numeric ? "number" : "text",
|
|
22996
|
+
value: draft,
|
|
22997
|
+
onChange: (e) => setDraft(e.target.value),
|
|
22998
|
+
onBlur: commit,
|
|
22999
|
+
onKeyDown: (e) => {
|
|
23000
|
+
if (e.key === "Enter") commit();
|
|
23001
|
+
}
|
|
23002
|
+
}
|
|
23003
|
+
);
|
|
23004
|
+
}
|
|
23005
|
+
function isTraitConfigObject(v) {
|
|
23006
|
+
return v !== null && v !== void 0 && typeof v === "object" && !Array.isArray(v);
|
|
23007
|
+
}
|
|
23008
|
+
function FieldControl({
|
|
23009
|
+
name,
|
|
23010
|
+
decl,
|
|
23011
|
+
value,
|
|
23012
|
+
onChange,
|
|
23013
|
+
assets
|
|
23014
|
+
}) {
|
|
23015
|
+
let control;
|
|
23016
|
+
const stringValue = typeof value === "string" ? value : void 0;
|
|
23017
|
+
const effectiveValue = value ?? decl.default;
|
|
23018
|
+
if (decl.type === "icon") {
|
|
23019
|
+
control = /* @__PURE__ */ jsx(IconPicker, { value: stringValue, onChange: (icon) => onChange(name, icon) });
|
|
23020
|
+
} else if (decl.type === "asset") {
|
|
23021
|
+
control = /* @__PURE__ */ jsx(
|
|
23022
|
+
AssetPicker,
|
|
23023
|
+
{
|
|
23024
|
+
assets: assets ?? [],
|
|
23025
|
+
value: stringValue,
|
|
23026
|
+
onChange: (url) => onChange(name, url)
|
|
23027
|
+
}
|
|
23028
|
+
);
|
|
23029
|
+
} else if (decl.type === "boolean") {
|
|
23030
|
+
control = /* @__PURE__ */ jsx(Switch, { checked: value === true, onChange: (c) => onChange(name, c) });
|
|
23031
|
+
} else if (decl.type === "string" && decl.values !== void 0 && decl.values.length > 0) {
|
|
23032
|
+
control = /* @__PURE__ */ jsx(
|
|
23033
|
+
Select,
|
|
23034
|
+
{
|
|
23035
|
+
options: decl.values.map((v) => ({ value: v, label: v })),
|
|
23036
|
+
value: typeof value === "string" ? value : "",
|
|
23037
|
+
onChange: (e) => onChange(name, e.target.value)
|
|
23038
|
+
}
|
|
23039
|
+
);
|
|
23040
|
+
} else if (decl.type === "number") {
|
|
23041
|
+
control = /* @__PURE__ */ jsx(TextLikeControl, { field: name, numeric: true, value, onCommit: onChange });
|
|
23042
|
+
} else if (decl.type === "string") {
|
|
23043
|
+
control = /* @__PURE__ */ jsx(TextLikeControl, { field: name, numeric: false, value, onCommit: onChange });
|
|
23044
|
+
} else if (decl.type === "node") {
|
|
23045
|
+
control = /* @__PURE__ */ jsx(NodeSlotEditor, { value: effectiveValue, onChange: (next) => onChange(name, next) });
|
|
23046
|
+
} else if (decl.type.startsWith("[") || Array.isArray(effectiveValue)) {
|
|
23047
|
+
const arr = Array.isArray(effectiveValue) ? effectiveValue : [];
|
|
23048
|
+
control = /* @__PURE__ */ jsx(JsonTreeEditor, { value: arr, onChange: (next) => onChange(name, next) });
|
|
23049
|
+
} else if (decl.type === "object" || decl.type.startsWith("Map ") || !SCALAR_TYPES.has(decl.type) && isTraitConfigObject(effectiveValue)) {
|
|
23050
|
+
const obj = isTraitConfigObject(effectiveValue) ? effectiveValue : {};
|
|
23051
|
+
control = /* @__PURE__ */ jsx(JsonTreeEditor, { value: obj, onChange: (next) => onChange(name, next) });
|
|
23052
|
+
} else {
|
|
23053
|
+
control = /* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "muted", children: [
|
|
23054
|
+
decl.type,
|
|
23055
|
+
" \u2014 edit in source"
|
|
23056
|
+
] });
|
|
23057
|
+
}
|
|
23058
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
23059
|
+
/* @__PURE__ */ jsx(Typography, { variant: "label", children: decl.label ?? name }),
|
|
23060
|
+
control,
|
|
23061
|
+
decl.description !== void 0 && decl.description !== "" && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: decl.description })
|
|
23062
|
+
] });
|
|
23063
|
+
}
|
|
23064
|
+
var TIER_ORDER, SCALAR_TYPES, PropertyInspector;
|
|
23065
|
+
var init_PropertyInspector = __esm({
|
|
23066
|
+
"components/core/molecules/PropertyInspector.tsx"() {
|
|
23067
|
+
"use client";
|
|
23068
|
+
init_cn();
|
|
23069
|
+
init_Stack();
|
|
23070
|
+
init_Typography();
|
|
23071
|
+
init_Button();
|
|
23072
|
+
init_Switch();
|
|
23073
|
+
init_Select();
|
|
23074
|
+
init_Input();
|
|
23075
|
+
init_FormSection();
|
|
23076
|
+
init_IconPicker();
|
|
23077
|
+
init_AssetPicker();
|
|
23078
|
+
init_JsonTreeEditor();
|
|
23079
|
+
init_NodeSlotEditor();
|
|
23080
|
+
TIER_ORDER = ["presentation", "domain", "policy", "infra", "internal"];
|
|
23081
|
+
SCALAR_TYPES = /* @__PURE__ */ new Set(["string", "number", "boolean", "icon", "asset"]);
|
|
23082
|
+
PropertyInspector = ({
|
|
23083
|
+
config,
|
|
23084
|
+
values,
|
|
23085
|
+
onChange,
|
|
23086
|
+
onReset,
|
|
23087
|
+
title,
|
|
23088
|
+
className,
|
|
23089
|
+
assets
|
|
23090
|
+
}) => {
|
|
23091
|
+
const fields = Object.entries(config);
|
|
23092
|
+
const byTier = /* @__PURE__ */ new Map();
|
|
23093
|
+
for (const [name, decl] of fields) {
|
|
23094
|
+
const tier = decl.tier ?? "presentation";
|
|
23095
|
+
const arr = byTier.get(tier) ?? [];
|
|
23096
|
+
arr.push([name, decl]);
|
|
23097
|
+
byTier.set(tier, arr);
|
|
23098
|
+
}
|
|
23099
|
+
const tiers = [...byTier.keys()].sort((a, b) => {
|
|
23100
|
+
const ia = TIER_ORDER.indexOf(a);
|
|
23101
|
+
const ib = TIER_ORDER.indexOf(b);
|
|
23102
|
+
return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib);
|
|
23103
|
+
});
|
|
23104
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("w-full", className), children: [
|
|
23105
|
+
/* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
|
|
23106
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", weight: "bold", children: title ?? "Config" }),
|
|
23107
|
+
onReset !== void 0 && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", icon: "rotate-ccw", label: "Reset", onClick: onReset })
|
|
23108
|
+
] }),
|
|
23109
|
+
fields.length === 0 && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: "No configurable properties." }),
|
|
23110
|
+
tiers.map((tier) => /* @__PURE__ */ jsx(FormSection, { title: tier, collapsible: true, defaultCollapsed: tier !== "presentation", children: /* @__PURE__ */ jsx(VStack, { gap: "sm", children: byTier.get(tier)?.map(([name, decl]) => /* @__PURE__ */ jsx(
|
|
23111
|
+
FieldControl,
|
|
23112
|
+
{
|
|
23113
|
+
name,
|
|
23114
|
+
decl,
|
|
23115
|
+
value: currentValue(decl, values?.[name]),
|
|
23116
|
+
onChange,
|
|
23117
|
+
assets
|
|
23118
|
+
},
|
|
23119
|
+
name
|
|
23120
|
+
)) }) }, tier))
|
|
23121
|
+
] });
|
|
23122
|
+
};
|
|
23123
|
+
}
|
|
23124
|
+
});
|
|
22479
23125
|
function normalize(value) {
|
|
22480
23126
|
const wasArray = Array.isArray(value);
|
|
22481
23127
|
const pattern = wasArray ? value[0] : value;
|
|
@@ -22494,6 +23140,7 @@ var init_NodeSlotEditor = __esm({
|
|
|
22494
23140
|
init_Select();
|
|
22495
23141
|
init_Typography();
|
|
22496
23142
|
init_JsonTreeEditor();
|
|
23143
|
+
init_PropertyInspector();
|
|
22497
23144
|
init_pattern_resolver();
|
|
22498
23145
|
init_cn();
|
|
22499
23146
|
isObj2 = (v) => v !== null && v !== void 0 && typeof v === "object" && !Array.isArray(v);
|
|
@@ -22518,6 +23165,21 @@ var init_NodeSlotEditor = __esm({
|
|
|
22518
23165
|
const pattern = { type: nextType, ...nextProps };
|
|
22519
23166
|
onChange(wasArray || value === void 0 ? [pattern] : pattern);
|
|
22520
23167
|
};
|
|
23168
|
+
const schemaEntries = React74__default.useMemo(() => {
|
|
23169
|
+
if (!type) return [];
|
|
23170
|
+
const def = getPatternDefinition(type);
|
|
23171
|
+
if (!def?.propsSchema) return [];
|
|
23172
|
+
return Object.entries(def.propsSchema).map(([propName, propDef]) => {
|
|
23173
|
+
const decl = {
|
|
23174
|
+
type: propDef.types?.[0] ?? "string",
|
|
23175
|
+
description: propDef.description,
|
|
23176
|
+
label: propName,
|
|
23177
|
+
...propDef.enumValues && propDef.enumValues.length > 0 ? { values: propDef.enumValues } : {}
|
|
23178
|
+
};
|
|
23179
|
+
return [propName, decl];
|
|
23180
|
+
});
|
|
23181
|
+
}, [type]);
|
|
23182
|
+
const hasSchema = schemaEntries.length > 0;
|
|
22521
23183
|
return /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: cn("w-full", className), children: [
|
|
22522
23184
|
/* @__PURE__ */ jsx(
|
|
22523
23185
|
Select,
|
|
@@ -22529,7 +23191,16 @@ var init_NodeSlotEditor = __esm({
|
|
|
22529
23191
|
),
|
|
22530
23192
|
type !== "" && /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "pl-1", children: [
|
|
22531
23193
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: "props" }),
|
|
22532
|
-
/* @__PURE__ */ jsx(
|
|
23194
|
+
hasSchema ? /* @__PURE__ */ jsx(VStack, { gap: "xs", children: schemaEntries.map(([propName, decl]) => /* @__PURE__ */ jsx(
|
|
23195
|
+
FieldControl,
|
|
23196
|
+
{
|
|
23197
|
+
name: propName,
|
|
23198
|
+
decl,
|
|
23199
|
+
value: props[propName],
|
|
23200
|
+
onChange: (field, val) => emit(type, { ...props, [field]: val })
|
|
23201
|
+
},
|
|
23202
|
+
propName
|
|
23203
|
+
)) }) : /* @__PURE__ */ jsx(JsonTreeEditor, { value: props, onChange: (next) => emit(type, isObj2(next) ? next : {}) })
|
|
22533
23204
|
] })
|
|
22534
23205
|
] });
|
|
22535
23206
|
};
|
|
@@ -25112,303 +25783,6 @@ var init_FlipCard = __esm({
|
|
|
25112
25783
|
FlipCard.displayName = "FlipCard";
|
|
25113
25784
|
}
|
|
25114
25785
|
});
|
|
25115
|
-
var ALL_CATEGORY, GridPicker;
|
|
25116
|
-
var init_GridPicker = __esm({
|
|
25117
|
-
"components/core/molecules/GridPicker.tsx"() {
|
|
25118
|
-
"use client";
|
|
25119
|
-
init_cn();
|
|
25120
|
-
init_Input();
|
|
25121
|
-
init_Badge();
|
|
25122
|
-
init_Stack();
|
|
25123
|
-
ALL_CATEGORY = "__all__";
|
|
25124
|
-
GridPicker = ({
|
|
25125
|
-
items,
|
|
25126
|
-
value,
|
|
25127
|
-
onChange,
|
|
25128
|
-
categories,
|
|
25129
|
-
searchPlaceholder,
|
|
25130
|
-
renderThumbnail,
|
|
25131
|
-
cellSize = 32,
|
|
25132
|
-
className
|
|
25133
|
-
}) => {
|
|
25134
|
-
const [search, setSearch] = useState("");
|
|
25135
|
-
const [activeCategory, setActiveCategory] = useState(ALL_CATEGORY);
|
|
25136
|
-
const gridRef = useRef(null);
|
|
25137
|
-
const categoryChips = useMemo(() => {
|
|
25138
|
-
if (categories !== void 0) return categories;
|
|
25139
|
-
const seen = [];
|
|
25140
|
-
for (const item of items) {
|
|
25141
|
-
if (!seen.includes(item.category)) seen.push(item.category);
|
|
25142
|
-
}
|
|
25143
|
-
return seen;
|
|
25144
|
-
}, [categories, items]);
|
|
25145
|
-
const filtered = useMemo(() => {
|
|
25146
|
-
const needle = search.trim().toLowerCase();
|
|
25147
|
-
return items.filter((item) => {
|
|
25148
|
-
const matchesCategory = activeCategory === ALL_CATEGORY || item.category === activeCategory;
|
|
25149
|
-
const matchesSearch = needle === "" || item.label.toLowerCase().includes(needle);
|
|
25150
|
-
return matchesCategory && matchesSearch;
|
|
25151
|
-
});
|
|
25152
|
-
}, [items, search, activeCategory]);
|
|
25153
|
-
const select = useCallback(
|
|
25154
|
-
(item) => {
|
|
25155
|
-
onChange(item.id);
|
|
25156
|
-
},
|
|
25157
|
-
[onChange]
|
|
25158
|
-
);
|
|
25159
|
-
const handleKeyDown = useCallback(
|
|
25160
|
-
(e, index) => {
|
|
25161
|
-
const cells = gridRef.current?.querySelectorAll(
|
|
25162
|
-
"[data-gridpicker-cell]"
|
|
25163
|
-
);
|
|
25164
|
-
if (cells === void 0 || cells.length === 0) return;
|
|
25165
|
-
const columns = (() => {
|
|
25166
|
-
const grid = gridRef.current;
|
|
25167
|
-
if (grid === null) return 1;
|
|
25168
|
-
const style = window.getComputedStyle(grid);
|
|
25169
|
-
const cols = style.gridTemplateColumns.split(" ").filter(Boolean).length;
|
|
25170
|
-
return cols > 0 ? cols : 1;
|
|
25171
|
-
})();
|
|
25172
|
-
let next = -1;
|
|
25173
|
-
if (e.key === "ArrowRight") next = index + 1;
|
|
25174
|
-
else if (e.key === "ArrowLeft") next = index - 1;
|
|
25175
|
-
else if (e.key === "ArrowDown") next = index + columns;
|
|
25176
|
-
else if (e.key === "ArrowUp") next = index - columns;
|
|
25177
|
-
else if (e.key === "Enter" || e.key === " ") {
|
|
25178
|
-
e.preventDefault();
|
|
25179
|
-
select(filtered[index]);
|
|
25180
|
-
return;
|
|
25181
|
-
} else {
|
|
25182
|
-
return;
|
|
25183
|
-
}
|
|
25184
|
-
e.preventDefault();
|
|
25185
|
-
if (next >= 0 && next < cells.length) {
|
|
25186
|
-
cells[next].focus();
|
|
25187
|
-
}
|
|
25188
|
-
},
|
|
25189
|
-
[filtered, select]
|
|
25190
|
-
);
|
|
25191
|
-
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("w-full", className), children: [
|
|
25192
|
-
/* @__PURE__ */ jsx(
|
|
25193
|
-
Input,
|
|
25194
|
-
{
|
|
25195
|
-
type: "search",
|
|
25196
|
-
icon: "search",
|
|
25197
|
-
value: search,
|
|
25198
|
-
placeholder: searchPlaceholder,
|
|
25199
|
-
clearable: true,
|
|
25200
|
-
onClear: () => setSearch(""),
|
|
25201
|
-
onChange: (e) => setSearch(e.target.value)
|
|
25202
|
-
}
|
|
25203
|
-
),
|
|
25204
|
-
categoryChips.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", wrap: true, children: [
|
|
25205
|
-
/* @__PURE__ */ jsx(
|
|
25206
|
-
Badge,
|
|
25207
|
-
{
|
|
25208
|
-
variant: activeCategory === ALL_CATEGORY ? "primary" : "neutral",
|
|
25209
|
-
size: "sm",
|
|
25210
|
-
role: "button",
|
|
25211
|
-
tabIndex: 0,
|
|
25212
|
-
"aria-pressed": activeCategory === ALL_CATEGORY,
|
|
25213
|
-
className: "cursor-pointer",
|
|
25214
|
-
onClick: () => setActiveCategory(ALL_CATEGORY),
|
|
25215
|
-
onKeyDown: (e) => {
|
|
25216
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
25217
|
-
e.preventDefault();
|
|
25218
|
-
setActiveCategory(ALL_CATEGORY);
|
|
25219
|
-
}
|
|
25220
|
-
},
|
|
25221
|
-
children: "All"
|
|
25222
|
-
}
|
|
25223
|
-
),
|
|
25224
|
-
categoryChips.map((category) => /* @__PURE__ */ jsx(
|
|
25225
|
-
Badge,
|
|
25226
|
-
{
|
|
25227
|
-
variant: activeCategory === category ? "primary" : "neutral",
|
|
25228
|
-
size: "sm",
|
|
25229
|
-
role: "button",
|
|
25230
|
-
tabIndex: 0,
|
|
25231
|
-
"aria-pressed": activeCategory === category,
|
|
25232
|
-
className: "cursor-pointer",
|
|
25233
|
-
onClick: () => setActiveCategory(category),
|
|
25234
|
-
onKeyDown: (e) => {
|
|
25235
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
25236
|
-
e.preventDefault();
|
|
25237
|
-
setActiveCategory(category);
|
|
25238
|
-
}
|
|
25239
|
-
},
|
|
25240
|
-
children: category
|
|
25241
|
-
},
|
|
25242
|
-
category
|
|
25243
|
-
))
|
|
25244
|
-
] }),
|
|
25245
|
-
/* @__PURE__ */ jsx(
|
|
25246
|
-
"div",
|
|
25247
|
-
{
|
|
25248
|
-
ref: gridRef,
|
|
25249
|
-
role: "listbox",
|
|
25250
|
-
className: "grid gap-1 overflow-y-auto max-h-64 p-1",
|
|
25251
|
-
style: {
|
|
25252
|
-
gridTemplateColumns: `repeat(auto-fill, minmax(${cellSize}px, 1fr))`
|
|
25253
|
-
},
|
|
25254
|
-
children: filtered.map((item, index) => {
|
|
25255
|
-
const selected = item.id === value;
|
|
25256
|
-
return /* @__PURE__ */ jsx(
|
|
25257
|
-
"button",
|
|
25258
|
-
{
|
|
25259
|
-
type: "button",
|
|
25260
|
-
role: "option",
|
|
25261
|
-
"aria-selected": selected,
|
|
25262
|
-
"aria-label": item.label,
|
|
25263
|
-
title: item.label,
|
|
25264
|
-
"data-gridpicker-cell": true,
|
|
25265
|
-
tabIndex: selected || value === void 0 && index === 0 ? 0 : -1,
|
|
25266
|
-
onClick: () => select(item),
|
|
25267
|
-
onKeyDown: (e) => handleKeyDown(e, index),
|
|
25268
|
-
className: cn(
|
|
25269
|
-
"flex items-center justify-center rounded-sm",
|
|
25270
|
-
"transition-colors hover:bg-muted",
|
|
25271
|
-
"focus:outline-none focus:ring-1 focus:ring-ring",
|
|
25272
|
-
selected && "bg-primary/10 ring-1 ring-primary"
|
|
25273
|
-
),
|
|
25274
|
-
style: { width: cellSize, height: cellSize },
|
|
25275
|
-
children: renderThumbnail(item)
|
|
25276
|
-
},
|
|
25277
|
-
item.id
|
|
25278
|
-
);
|
|
25279
|
-
})
|
|
25280
|
-
}
|
|
25281
|
-
)
|
|
25282
|
-
] });
|
|
25283
|
-
};
|
|
25284
|
-
GridPicker.displayName = "GridPicker";
|
|
25285
|
-
}
|
|
25286
|
-
});
|
|
25287
|
-
function iconForKind(kind) {
|
|
25288
|
-
if (kind === "audio") return "music";
|
|
25289
|
-
if (kind === "model") return "box";
|
|
25290
|
-
return "file";
|
|
25291
|
-
}
|
|
25292
|
-
var THUMB_PX, IMAGE_KINDS, AssetPicker;
|
|
25293
|
-
var init_AssetPicker = __esm({
|
|
25294
|
-
"components/core/molecules/AssetPicker.tsx"() {
|
|
25295
|
-
"use client";
|
|
25296
|
-
init_GridPicker();
|
|
25297
|
-
init_Icon();
|
|
25298
|
-
THUMB_PX = 32;
|
|
25299
|
-
IMAGE_KINDS = /* @__PURE__ */ new Set([
|
|
25300
|
-
"image",
|
|
25301
|
-
"spritesheet",
|
|
25302
|
-
"scene",
|
|
25303
|
-
"portrait"
|
|
25304
|
-
]);
|
|
25305
|
-
AssetPicker = ({
|
|
25306
|
-
assets,
|
|
25307
|
-
value,
|
|
25308
|
-
onChange,
|
|
25309
|
-
className
|
|
25310
|
-
}) => {
|
|
25311
|
-
const byUrl = useMemo(() => {
|
|
25312
|
-
const map = /* @__PURE__ */ new Map();
|
|
25313
|
-
for (const entry of assets) map.set(entry.url, entry);
|
|
25314
|
-
return map;
|
|
25315
|
-
}, [assets]);
|
|
25316
|
-
const items = useMemo(
|
|
25317
|
-
() => assets.map((entry) => ({
|
|
25318
|
-
id: entry.url,
|
|
25319
|
-
label: entry.name,
|
|
25320
|
-
category: entry.category
|
|
25321
|
-
})),
|
|
25322
|
-
[assets]
|
|
25323
|
-
);
|
|
25324
|
-
const categories = useMemo(() => {
|
|
25325
|
-
const seen = [];
|
|
25326
|
-
for (const entry of assets) {
|
|
25327
|
-
if (!seen.includes(entry.category)) seen.push(entry.category);
|
|
25328
|
-
}
|
|
25329
|
-
return seen;
|
|
25330
|
-
}, [assets]);
|
|
25331
|
-
const renderThumbnail = useCallback(
|
|
25332
|
-
(item) => {
|
|
25333
|
-
const entry = byUrl.get(item.id);
|
|
25334
|
-
if (entry === void 0) return null;
|
|
25335
|
-
if (IMAGE_KINDS.has(entry.kind)) {
|
|
25336
|
-
return /* @__PURE__ */ jsx(
|
|
25337
|
-
"img",
|
|
25338
|
-
{
|
|
25339
|
-
src: entry.thumbnailUrl ?? entry.url,
|
|
25340
|
-
alt: entry.name,
|
|
25341
|
-
loading: "lazy",
|
|
25342
|
-
width: THUMB_PX,
|
|
25343
|
-
height: THUMB_PX,
|
|
25344
|
-
style: { width: THUMB_PX, height: THUMB_PX, objectFit: "cover" }
|
|
25345
|
-
}
|
|
25346
|
-
);
|
|
25347
|
-
}
|
|
25348
|
-
return /* @__PURE__ */ jsx(Icon, { name: iconForKind(entry.kind), size: "sm" });
|
|
25349
|
-
},
|
|
25350
|
-
[byUrl]
|
|
25351
|
-
);
|
|
25352
|
-
return /* @__PURE__ */ jsx(
|
|
25353
|
-
GridPicker,
|
|
25354
|
-
{
|
|
25355
|
-
items,
|
|
25356
|
-
value,
|
|
25357
|
-
onChange,
|
|
25358
|
-
categories,
|
|
25359
|
-
renderThumbnail,
|
|
25360
|
-
cellSize: THUMB_PX,
|
|
25361
|
-
className
|
|
25362
|
-
}
|
|
25363
|
-
);
|
|
25364
|
-
};
|
|
25365
|
-
AssetPicker.displayName = "AssetPicker";
|
|
25366
|
-
}
|
|
25367
|
-
});
|
|
25368
|
-
function pascalToKebab(name) {
|
|
25369
|
-
return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
25370
|
-
}
|
|
25371
|
-
function kebabToPascal3(name) {
|
|
25372
|
-
return name.split("-").map((part) => /^\d+$/.test(part) ? part : part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
25373
|
-
}
|
|
25374
|
-
var ICON_ITEMS, IconPicker;
|
|
25375
|
-
var init_IconPicker = __esm({
|
|
25376
|
-
"components/core/molecules/IconPicker.tsx"() {
|
|
25377
|
-
"use client";
|
|
25378
|
-
init_Icon();
|
|
25379
|
-
init_GridPicker();
|
|
25380
|
-
ICON_ITEMS = (() => {
|
|
25381
|
-
const items = [];
|
|
25382
|
-
for (const [exportName, candidate] of Object.entries(LucideIcons2)) {
|
|
25383
|
-
if (!/^[A-Z]/.test(exportName)) continue;
|
|
25384
|
-
if (exportName.endsWith("Icon")) continue;
|
|
25385
|
-
if (exportName.startsWith("Lucide")) continue;
|
|
25386
|
-
const isComponent = candidate !== null && (typeof candidate === "object" || typeof candidate === "function") && "$$typeof" in candidate;
|
|
25387
|
-
if (!isComponent) continue;
|
|
25388
|
-
const kebab = pascalToKebab(exportName);
|
|
25389
|
-
if (kebabToPascal3(kebab) !== exportName) continue;
|
|
25390
|
-
items.push({ id: kebab, label: kebab, category: "icons" });
|
|
25391
|
-
}
|
|
25392
|
-
return items;
|
|
25393
|
-
})();
|
|
25394
|
-
IconPicker = ({ value, onChange, className }) => {
|
|
25395
|
-
const items = useMemo(() => ICON_ITEMS, []);
|
|
25396
|
-
return /* @__PURE__ */ jsx(
|
|
25397
|
-
GridPicker,
|
|
25398
|
-
{
|
|
25399
|
-
items,
|
|
25400
|
-
value,
|
|
25401
|
-
onChange,
|
|
25402
|
-
searchPlaceholder: "Search icons\u2026",
|
|
25403
|
-
renderThumbnail: (it) => /* @__PURE__ */ jsx(Icon, { name: it.id }),
|
|
25404
|
-
cellSize: 32,
|
|
25405
|
-
className
|
|
25406
|
-
}
|
|
25407
|
-
);
|
|
25408
|
-
};
|
|
25409
|
-
IconPicker.displayName = "IconPicker";
|
|
25410
|
-
}
|
|
25411
|
-
});
|
|
25412
25786
|
function toISODate(d) {
|
|
25413
25787
|
return d.toISOString().slice(0, 10);
|
|
25414
25788
|
}
|
|
@@ -35099,286 +35473,6 @@ var init_PageHeader = __esm({
|
|
|
35099
35473
|
PageHeader.displayName = "PageHeader";
|
|
35100
35474
|
}
|
|
35101
35475
|
});
|
|
35102
|
-
var FormSection, FormLayout, FormActions;
|
|
35103
|
-
var init_FormSection = __esm({
|
|
35104
|
-
"components/core/molecules/FormSection.tsx"() {
|
|
35105
|
-
"use client";
|
|
35106
|
-
init_cn();
|
|
35107
|
-
init_atoms2();
|
|
35108
|
-
init_Box();
|
|
35109
|
-
init_Typography();
|
|
35110
|
-
init_Button();
|
|
35111
|
-
init_Stack();
|
|
35112
|
-
init_Icon();
|
|
35113
|
-
init_useEventBus();
|
|
35114
|
-
FormSection = ({
|
|
35115
|
-
title,
|
|
35116
|
-
description,
|
|
35117
|
-
children,
|
|
35118
|
-
collapsible = false,
|
|
35119
|
-
defaultCollapsed = false,
|
|
35120
|
-
card = false,
|
|
35121
|
-
columns = 1,
|
|
35122
|
-
className
|
|
35123
|
-
}) => {
|
|
35124
|
-
const [collapsed, setCollapsed] = React74__default.useState(defaultCollapsed);
|
|
35125
|
-
const { t } = useTranslate();
|
|
35126
|
-
const eventBus = useEventBus();
|
|
35127
|
-
const gridClass = {
|
|
35128
|
-
1: "grid-cols-1",
|
|
35129
|
-
2: "grid-cols-1 md:grid-cols-2",
|
|
35130
|
-
3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
|
|
35131
|
-
}[columns];
|
|
35132
|
-
React74__default.useCallback(() => {
|
|
35133
|
-
if (collapsible) {
|
|
35134
|
-
setCollapsed((prev) => !prev);
|
|
35135
|
-
eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
|
|
35136
|
-
}
|
|
35137
|
-
}, [collapsible, collapsed, eventBus]);
|
|
35138
|
-
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
35139
|
-
(title || description) && /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "mb-4", children: [
|
|
35140
|
-
title && /* @__PURE__ */ jsxs(
|
|
35141
|
-
HStack,
|
|
35142
|
-
{
|
|
35143
|
-
justify: "between",
|
|
35144
|
-
align: "center",
|
|
35145
|
-
className: cn(collapsible && "cursor-pointer"),
|
|
35146
|
-
action: collapsible ? "TOGGLE_COLLAPSE" : void 0,
|
|
35147
|
-
children: [
|
|
35148
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "semibold", children: title }),
|
|
35149
|
-
collapsible && /* @__PURE__ */ jsx(
|
|
35150
|
-
Button,
|
|
35151
|
-
{
|
|
35152
|
-
variant: "ghost",
|
|
35153
|
-
size: "sm",
|
|
35154
|
-
action: "TOGGLE_COLLAPSE",
|
|
35155
|
-
children: /* @__PURE__ */ jsx(
|
|
35156
|
-
Icon,
|
|
35157
|
-
{
|
|
35158
|
-
icon: ChevronDown,
|
|
35159
|
-
size: "sm",
|
|
35160
|
-
className: cn(
|
|
35161
|
-
"text-muted-foreground transition-transform",
|
|
35162
|
-
collapsed && "rotate-180"
|
|
35163
|
-
)
|
|
35164
|
-
}
|
|
35165
|
-
)
|
|
35166
|
-
}
|
|
35167
|
-
)
|
|
35168
|
-
]
|
|
35169
|
-
}
|
|
35170
|
-
),
|
|
35171
|
-
description && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: description })
|
|
35172
|
-
] }),
|
|
35173
|
-
(!collapsible || !collapsed) && /* @__PURE__ */ jsx(Box, { className: cn("grid gap-4", gridClass), children })
|
|
35174
|
-
] });
|
|
35175
|
-
if (card) {
|
|
35176
|
-
return /* @__PURE__ */ jsx(Card, { className: cn("p-6", className), children: content });
|
|
35177
|
-
}
|
|
35178
|
-
return /* @__PURE__ */ jsx(Box, { className, children: content });
|
|
35179
|
-
};
|
|
35180
|
-
FormSection.displayName = "FormSection";
|
|
35181
|
-
FormLayout = ({
|
|
35182
|
-
children,
|
|
35183
|
-
dividers = true,
|
|
35184
|
-
className
|
|
35185
|
-
}) => {
|
|
35186
|
-
return /* @__PURE__ */ jsx(
|
|
35187
|
-
VStack,
|
|
35188
|
-
{
|
|
35189
|
-
gap: "lg",
|
|
35190
|
-
className: cn(
|
|
35191
|
-
dividers && "[&>*+*]:pt-8 [&>*+*]:border-t [&>*+*]:border-border",
|
|
35192
|
-
className
|
|
35193
|
-
),
|
|
35194
|
-
children
|
|
35195
|
-
}
|
|
35196
|
-
);
|
|
35197
|
-
};
|
|
35198
|
-
FormLayout.displayName = "FormLayout";
|
|
35199
|
-
FormActions = ({
|
|
35200
|
-
children,
|
|
35201
|
-
sticky = false,
|
|
35202
|
-
align = "right",
|
|
35203
|
-
className
|
|
35204
|
-
}) => {
|
|
35205
|
-
const alignClass2 = {
|
|
35206
|
-
left: "justify-start",
|
|
35207
|
-
right: "justify-end",
|
|
35208
|
-
between: "justify-between",
|
|
35209
|
-
center: "justify-center"
|
|
35210
|
-
}[align];
|
|
35211
|
-
return /* @__PURE__ */ jsx(
|
|
35212
|
-
HStack,
|
|
35213
|
-
{
|
|
35214
|
-
gap: "sm",
|
|
35215
|
-
align: "center",
|
|
35216
|
-
className: cn(
|
|
35217
|
-
"pt-6 border-t border-border",
|
|
35218
|
-
alignClass2,
|
|
35219
|
-
sticky && "sticky bottom-0 bg-card py-4 -mx-6 px-6 shadow-[0_-4px_6px_-1px_rgb(0,0,0,0.05)]",
|
|
35220
|
-
className
|
|
35221
|
-
),
|
|
35222
|
-
children
|
|
35223
|
-
}
|
|
35224
|
-
);
|
|
35225
|
-
};
|
|
35226
|
-
FormActions.displayName = "FormActions";
|
|
35227
|
-
}
|
|
35228
|
-
});
|
|
35229
|
-
function currentValue(decl, override) {
|
|
35230
|
-
return override !== void 0 ? override : decl.default;
|
|
35231
|
-
}
|
|
35232
|
-
function TextLikeControl({
|
|
35233
|
-
field,
|
|
35234
|
-
numeric,
|
|
35235
|
-
value,
|
|
35236
|
-
onCommit
|
|
35237
|
-
}) {
|
|
35238
|
-
const initial = value === void 0 || value === null ? "" : String(value);
|
|
35239
|
-
const [draft, setDraft] = React74__default.useState(initial);
|
|
35240
|
-
React74__default.useEffect(() => setDraft(initial), [initial]);
|
|
35241
|
-
const commit = () => {
|
|
35242
|
-
if (numeric) {
|
|
35243
|
-
const n = draft.trim() === "" ? 0 : Number(draft);
|
|
35244
|
-
onCommit(field, Number.isNaN(n) ? 0 : n);
|
|
35245
|
-
} else {
|
|
35246
|
-
onCommit(field, draft);
|
|
35247
|
-
}
|
|
35248
|
-
};
|
|
35249
|
-
return /* @__PURE__ */ jsx(
|
|
35250
|
-
Input,
|
|
35251
|
-
{
|
|
35252
|
-
inputType: numeric ? "number" : "text",
|
|
35253
|
-
value: draft,
|
|
35254
|
-
onChange: (e) => setDraft(e.target.value),
|
|
35255
|
-
onBlur: commit,
|
|
35256
|
-
onKeyDown: (e) => {
|
|
35257
|
-
if (e.key === "Enter") commit();
|
|
35258
|
-
}
|
|
35259
|
-
}
|
|
35260
|
-
);
|
|
35261
|
-
}
|
|
35262
|
-
function isTraitConfigObject(v) {
|
|
35263
|
-
return v !== null && v !== void 0 && typeof v === "object" && !Array.isArray(v);
|
|
35264
|
-
}
|
|
35265
|
-
function FieldControl({
|
|
35266
|
-
name,
|
|
35267
|
-
decl,
|
|
35268
|
-
value,
|
|
35269
|
-
onChange,
|
|
35270
|
-
assets
|
|
35271
|
-
}) {
|
|
35272
|
-
let control;
|
|
35273
|
-
const stringValue = typeof value === "string" ? value : void 0;
|
|
35274
|
-
const effectiveValue = value ?? decl.default;
|
|
35275
|
-
if (decl.type === "icon") {
|
|
35276
|
-
control = /* @__PURE__ */ jsx(IconPicker, { value: stringValue, onChange: (icon) => onChange(name, icon) });
|
|
35277
|
-
} else if (decl.type === "asset") {
|
|
35278
|
-
control = /* @__PURE__ */ jsx(
|
|
35279
|
-
AssetPicker,
|
|
35280
|
-
{
|
|
35281
|
-
assets: assets ?? [],
|
|
35282
|
-
value: stringValue,
|
|
35283
|
-
onChange: (url) => onChange(name, url)
|
|
35284
|
-
}
|
|
35285
|
-
);
|
|
35286
|
-
} else if (decl.type === "boolean") {
|
|
35287
|
-
control = /* @__PURE__ */ jsx(Switch, { checked: value === true, onChange: (c) => onChange(name, c) });
|
|
35288
|
-
} else if (decl.type === "string" && decl.values !== void 0 && decl.values.length > 0) {
|
|
35289
|
-
control = /* @__PURE__ */ jsx(
|
|
35290
|
-
Select,
|
|
35291
|
-
{
|
|
35292
|
-
options: decl.values.map((v) => ({ value: v, label: v })),
|
|
35293
|
-
value: typeof value === "string" ? value : "",
|
|
35294
|
-
onChange: (e) => onChange(name, e.target.value)
|
|
35295
|
-
}
|
|
35296
|
-
);
|
|
35297
|
-
} else if (decl.type === "number") {
|
|
35298
|
-
control = /* @__PURE__ */ jsx(TextLikeControl, { field: name, numeric: true, value, onCommit: onChange });
|
|
35299
|
-
} else if (decl.type === "string") {
|
|
35300
|
-
control = /* @__PURE__ */ jsx(TextLikeControl, { field: name, numeric: false, value, onCommit: onChange });
|
|
35301
|
-
} else if (decl.type === "node") {
|
|
35302
|
-
control = /* @__PURE__ */ jsx(NodeSlotEditor, { value: effectiveValue, onChange: (next) => onChange(name, next) });
|
|
35303
|
-
} else if (decl.type.startsWith("[") || Array.isArray(effectiveValue)) {
|
|
35304
|
-
const arr = Array.isArray(effectiveValue) ? effectiveValue : [];
|
|
35305
|
-
control = /* @__PURE__ */ jsx(JsonTreeEditor, { value: arr, onChange: (next) => onChange(name, next) });
|
|
35306
|
-
} else if (decl.type === "object" || decl.type.startsWith("Map ") || !SCALAR_TYPES.has(decl.type) && isTraitConfigObject(effectiveValue)) {
|
|
35307
|
-
const obj = isTraitConfigObject(effectiveValue) ? effectiveValue : {};
|
|
35308
|
-
control = /* @__PURE__ */ jsx(JsonTreeEditor, { value: obj, onChange: (next) => onChange(name, next) });
|
|
35309
|
-
} else {
|
|
35310
|
-
control = /* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "muted", children: [
|
|
35311
|
-
decl.type,
|
|
35312
|
-
" \u2014 edit in source"
|
|
35313
|
-
] });
|
|
35314
|
-
}
|
|
35315
|
-
return /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
35316
|
-
/* @__PURE__ */ jsx(Typography, { variant: "label", children: decl.label ?? name }),
|
|
35317
|
-
control,
|
|
35318
|
-
decl.description !== void 0 && decl.description !== "" && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: decl.description })
|
|
35319
|
-
] });
|
|
35320
|
-
}
|
|
35321
|
-
var TIER_ORDER, SCALAR_TYPES, PropertyInspector;
|
|
35322
|
-
var init_PropertyInspector = __esm({
|
|
35323
|
-
"components/core/molecules/PropertyInspector.tsx"() {
|
|
35324
|
-
"use client";
|
|
35325
|
-
init_cn();
|
|
35326
|
-
init_Stack();
|
|
35327
|
-
init_Typography();
|
|
35328
|
-
init_Button();
|
|
35329
|
-
init_Switch();
|
|
35330
|
-
init_Select();
|
|
35331
|
-
init_Input();
|
|
35332
|
-
init_FormSection();
|
|
35333
|
-
init_IconPicker();
|
|
35334
|
-
init_AssetPicker();
|
|
35335
|
-
init_JsonTreeEditor();
|
|
35336
|
-
init_NodeSlotEditor();
|
|
35337
|
-
TIER_ORDER = ["presentation", "domain", "policy", "infra", "internal"];
|
|
35338
|
-
SCALAR_TYPES = /* @__PURE__ */ new Set(["string", "number", "boolean", "icon", "asset"]);
|
|
35339
|
-
PropertyInspector = ({
|
|
35340
|
-
config,
|
|
35341
|
-
values,
|
|
35342
|
-
onChange,
|
|
35343
|
-
onReset,
|
|
35344
|
-
title,
|
|
35345
|
-
className,
|
|
35346
|
-
assets
|
|
35347
|
-
}) => {
|
|
35348
|
-
const fields = Object.entries(config);
|
|
35349
|
-
const byTier = /* @__PURE__ */ new Map();
|
|
35350
|
-
for (const [name, decl] of fields) {
|
|
35351
|
-
const tier = decl.tier ?? "presentation";
|
|
35352
|
-
const arr = byTier.get(tier) ?? [];
|
|
35353
|
-
arr.push([name, decl]);
|
|
35354
|
-
byTier.set(tier, arr);
|
|
35355
|
-
}
|
|
35356
|
-
const tiers = [...byTier.keys()].sort((a, b) => {
|
|
35357
|
-
const ia = TIER_ORDER.indexOf(a);
|
|
35358
|
-
const ib = TIER_ORDER.indexOf(b);
|
|
35359
|
-
return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib);
|
|
35360
|
-
});
|
|
35361
|
-
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("w-full", className), children: [
|
|
35362
|
-
/* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
|
|
35363
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", weight: "bold", children: title ?? "Config" }),
|
|
35364
|
-
onReset !== void 0 && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", icon: "rotate-ccw", label: "Reset", onClick: onReset })
|
|
35365
|
-
] }),
|
|
35366
|
-
fields.length === 0 && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: "No configurable properties." }),
|
|
35367
|
-
tiers.map((tier) => /* @__PURE__ */ jsx(FormSection, { title: tier, collapsible: true, defaultCollapsed: tier !== "presentation", children: /* @__PURE__ */ jsx(VStack, { gap: "sm", children: byTier.get(tier)?.map(([name, decl]) => /* @__PURE__ */ jsx(
|
|
35368
|
-
FieldControl,
|
|
35369
|
-
{
|
|
35370
|
-
name,
|
|
35371
|
-
decl,
|
|
35372
|
-
value: currentValue(decl, values?.[name]),
|
|
35373
|
-
onChange,
|
|
35374
|
-
assets
|
|
35375
|
-
},
|
|
35376
|
-
name
|
|
35377
|
-
)) }) }, tier))
|
|
35378
|
-
] });
|
|
35379
|
-
};
|
|
35380
|
-
}
|
|
35381
|
-
});
|
|
35382
35476
|
var lookStyles8, Header;
|
|
35383
35477
|
var init_Header = __esm({
|
|
35384
35478
|
"components/core/molecules/Header.tsx"() {
|
|
@@ -36734,7 +36828,6 @@ var init_DocumentViewer = __esm({
|
|
|
36734
36828
|
showPrint = false,
|
|
36735
36829
|
actions,
|
|
36736
36830
|
documents,
|
|
36737
|
-
entity,
|
|
36738
36831
|
isLoading = false,
|
|
36739
36832
|
error,
|
|
36740
36833
|
className
|
|
@@ -43904,7 +43997,7 @@ function TraitSlot({
|
|
|
43904
43997
|
size = "md",
|
|
43905
43998
|
showTooltip = true,
|
|
43906
43999
|
categoryColors,
|
|
43907
|
-
tooltipFrameUrl,
|
|
44000
|
+
tooltipFrameUrl = "",
|
|
43908
44001
|
className,
|
|
43909
44002
|
feedback,
|
|
43910
44003
|
onItemDrop,
|
|
@@ -48402,7 +48495,7 @@ function SlotContentRenderer({
|
|
|
48402
48495
|
const { children: _childrenConfig, ...restPropsNoChildren } = content.props;
|
|
48403
48496
|
const restProps = childrenIsRenderFn ? { ...restPropsNoChildren, children: incomingChildren } : restPropsNoChildren;
|
|
48404
48497
|
const renderedProps = renderPatternProps(restProps, onDismiss);
|
|
48405
|
-
const patternDef = getPatternDefinition(content.pattern);
|
|
48498
|
+
const patternDef = getPatternDefinition$1(content.pattern);
|
|
48406
48499
|
const propsSchema = patternDef?.propsSchema;
|
|
48407
48500
|
if (propsSchema) {
|
|
48408
48501
|
for (const [propKey, propValue] of Object.entries(renderedProps)) {
|