@particle-academy/react-fancy 2.4.0 → 2.6.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/{diagram.serializers-OK4HP7AB.js → diagram.serializers-6RPUO46U.js} +11 -11
- package/dist/diagram.serializers-6RPUO46U.js.map +1 -0
- package/dist/index.cjs +403 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +210 -3
- package/dist/index.d.ts +210 -3
- package/dist/index.js +390 -46
- package/dist/index.js.map +1 -1
- package/docs/AccordionPanel.md +135 -0
- package/docs/Action.md +1 -1
- package/docs/ContentRenderer.md +26 -1
- package/package.json +1 -1
- package/dist/diagram.serializers-OK4HP7AB.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { forwardRef, useId, useRef, useEffect, useState, useCallback, useMemo,
|
|
1
|
+
import { forwardRef, createContext, useId, useRef, useEffect, useState, useCallback, useMemo, Children, isValidElement, cloneElement, useLayoutEffect, useContext, Fragment as Fragment$1 } from 'react';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
import { twMerge } from 'tailwind-merge';
|
|
4
4
|
import * as LucideIcons from 'lucide-react';
|
|
@@ -12,6 +12,80 @@ function cn(...inputs) {
|
|
|
12
12
|
return twMerge(clsx(inputs));
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
// src/utils/sanitize.ts
|
|
16
|
+
var DANGEROUS_TAGS = /* @__PURE__ */ new Set([
|
|
17
|
+
"script",
|
|
18
|
+
"style",
|
|
19
|
+
"iframe",
|
|
20
|
+
"object",
|
|
21
|
+
"embed",
|
|
22
|
+
"link",
|
|
23
|
+
"meta",
|
|
24
|
+
"base",
|
|
25
|
+
"form"
|
|
26
|
+
]);
|
|
27
|
+
var URL_ATTRS = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "xlink:href"]);
|
|
28
|
+
var SAFE_PROTOCOL = /^(?:https?:|mailto:|tel:|sms:|ftp:|#|\/|\.\/|\.\.\/|[^:]*$)/i;
|
|
29
|
+
function sanitizeHref(href) {
|
|
30
|
+
if (href == null) return void 0;
|
|
31
|
+
const trimmed = href.trim();
|
|
32
|
+
if (!trimmed) return void 0;
|
|
33
|
+
return SAFE_PROTOCOL.test(trimmed) ? trimmed : void 0;
|
|
34
|
+
}
|
|
35
|
+
function stripDangerousAttrs(el) {
|
|
36
|
+
const names = [];
|
|
37
|
+
for (let i = 0; i < el.attributes.length; i++) {
|
|
38
|
+
names.push(el.attributes[i].name);
|
|
39
|
+
}
|
|
40
|
+
for (const name of names) {
|
|
41
|
+
const lower = name.toLowerCase();
|
|
42
|
+
if (lower.startsWith("on")) {
|
|
43
|
+
el.removeAttribute(name);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (URL_ATTRS.has(lower)) {
|
|
47
|
+
const sanitized = sanitizeHref(el.getAttribute(name));
|
|
48
|
+
if (sanitized === void 0) {
|
|
49
|
+
el.removeAttribute(name);
|
|
50
|
+
} else {
|
|
51
|
+
el.setAttribute(name, sanitized);
|
|
52
|
+
}
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (lower === "srcdoc") {
|
|
56
|
+
el.removeAttribute(name);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function walk(el, removeQueue) {
|
|
61
|
+
const tag = el.tagName.toLowerCase();
|
|
62
|
+
if (DANGEROUS_TAGS.has(tag)) {
|
|
63
|
+
removeQueue.push(el);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
stripDangerousAttrs(el);
|
|
67
|
+
const children = Array.from(el.children);
|
|
68
|
+
for (const child of children) {
|
|
69
|
+
walk(child, removeQueue);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function sanitizeHtml(html) {
|
|
73
|
+
if (typeof window === "undefined" || typeof DOMParser === "undefined") {
|
|
74
|
+
return html;
|
|
75
|
+
}
|
|
76
|
+
const doc = new DOMParser().parseFromString(`<body>${html}</body>`, "text/html");
|
|
77
|
+
const body = doc.body;
|
|
78
|
+
if (!body) return html;
|
|
79
|
+
const removeQueue = [];
|
|
80
|
+
for (const child of Array.from(body.children)) {
|
|
81
|
+
walk(child, removeQueue);
|
|
82
|
+
}
|
|
83
|
+
for (const el of removeQueue) {
|
|
84
|
+
el.parentNode?.removeChild(el);
|
|
85
|
+
}
|
|
86
|
+
return body.innerHTML;
|
|
87
|
+
}
|
|
88
|
+
|
|
15
89
|
// src/data/emoji-data.ts
|
|
16
90
|
var EMOJI_CATEGORY_ORDER = [
|
|
17
91
|
"smileys",
|
|
@@ -2411,7 +2485,8 @@ var Action = forwardRef(
|
|
|
2411
2485
|
children != null && /* @__PURE__ */ jsx("span", { children }),
|
|
2412
2486
|
trailingElements
|
|
2413
2487
|
] });
|
|
2414
|
-
const
|
|
2488
|
+
const safeHref = sanitizeHref(href);
|
|
2489
|
+
const buttonEl = safeHref && !disabled ? /* @__PURE__ */ jsx("a", { href: safeHref, className: classes, "data-react-fancy-action": "", children: content }) : /* @__PURE__ */ jsx(
|
|
2415
2490
|
"button",
|
|
2416
2491
|
{
|
|
2417
2492
|
ref,
|
|
@@ -2481,6 +2556,283 @@ var Action = forwardRef(
|
|
|
2481
2556
|
}
|
|
2482
2557
|
);
|
|
2483
2558
|
Action.displayName = "Action";
|
|
2559
|
+
function useControllableState(controlledValue, defaultValue, onChange) {
|
|
2560
|
+
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
|
|
2561
|
+
const isControlled = controlledValue !== void 0;
|
|
2562
|
+
const value = isControlled ? controlledValue : uncontrolledValue;
|
|
2563
|
+
const onChangeRef = useRef(onChange);
|
|
2564
|
+
onChangeRef.current = onChange;
|
|
2565
|
+
const setValue = useCallback(
|
|
2566
|
+
(next) => {
|
|
2567
|
+
const nextValue = typeof next === "function" ? next(value) : next;
|
|
2568
|
+
if (!isControlled) {
|
|
2569
|
+
setUncontrolledValue(nextValue);
|
|
2570
|
+
}
|
|
2571
|
+
onChangeRef.current?.(nextValue);
|
|
2572
|
+
},
|
|
2573
|
+
[isControlled, value]
|
|
2574
|
+
);
|
|
2575
|
+
return [value, setValue];
|
|
2576
|
+
}
|
|
2577
|
+
var AccordionPanelContext = createContext(null);
|
|
2578
|
+
function useAccordionPanel() {
|
|
2579
|
+
const ctx = useContext(AccordionPanelContext);
|
|
2580
|
+
if (!ctx) {
|
|
2581
|
+
throw new Error(
|
|
2582
|
+
"AccordionPanel components must be used inside <AccordionPanel>"
|
|
2583
|
+
);
|
|
2584
|
+
}
|
|
2585
|
+
return ctx;
|
|
2586
|
+
}
|
|
2587
|
+
var AccordionSectionContext = createContext(null);
|
|
2588
|
+
function useAccordionSection() {
|
|
2589
|
+
const ctx = useContext(AccordionSectionContext);
|
|
2590
|
+
if (!ctx) {
|
|
2591
|
+
throw new Error(
|
|
2592
|
+
"<AccordionPanel.Trigger> must be rendered inside <AccordionPanel.Section>"
|
|
2593
|
+
);
|
|
2594
|
+
}
|
|
2595
|
+
return ctx;
|
|
2596
|
+
}
|
|
2597
|
+
function AccordionPanelSection({
|
|
2598
|
+
id,
|
|
2599
|
+
pinned = false,
|
|
2600
|
+
className,
|
|
2601
|
+
openClassName,
|
|
2602
|
+
closedClassName,
|
|
2603
|
+
children
|
|
2604
|
+
}) {
|
|
2605
|
+
const panel = useAccordionPanel();
|
|
2606
|
+
const { orientation, isOpen, toggle, registerSection } = panel;
|
|
2607
|
+
useEffect(() => registerSection(id), [id, registerSection]);
|
|
2608
|
+
const open = pinned || isOpen(id);
|
|
2609
|
+
const sectionCtx = useMemo(
|
|
2610
|
+
() => ({
|
|
2611
|
+
id,
|
|
2612
|
+
open,
|
|
2613
|
+
pinned,
|
|
2614
|
+
orientation,
|
|
2615
|
+
toggle: () => toggle(id)
|
|
2616
|
+
}),
|
|
2617
|
+
[id, open, pinned, orientation, toggle]
|
|
2618
|
+
);
|
|
2619
|
+
return /* @__PURE__ */ jsx(AccordionSectionContext.Provider, { value: sectionCtx, children: /* @__PURE__ */ jsx(
|
|
2620
|
+
"div",
|
|
2621
|
+
{
|
|
2622
|
+
"data-react-fancy-accordion-section": "",
|
|
2623
|
+
"data-state": open ? "open" : "closed",
|
|
2624
|
+
"data-pinned": pinned ? "" : void 0,
|
|
2625
|
+
"data-orientation": orientation,
|
|
2626
|
+
className: cn(
|
|
2627
|
+
"flex shrink-0 items-center gap-1",
|
|
2628
|
+
orientation === "horizontal" ? "flex-row" : "flex-col",
|
|
2629
|
+
className,
|
|
2630
|
+
open ? openClassName : closedClassName
|
|
2631
|
+
),
|
|
2632
|
+
children
|
|
2633
|
+
}
|
|
2634
|
+
) });
|
|
2635
|
+
}
|
|
2636
|
+
AccordionPanelSection.displayName = "AccordionPanelSection";
|
|
2637
|
+
function renderSlot(slot, state) {
|
|
2638
|
+
return typeof slot === "function" ? slot(state) : slot;
|
|
2639
|
+
}
|
|
2640
|
+
function AccordionPanelTrigger({
|
|
2641
|
+
children,
|
|
2642
|
+
className,
|
|
2643
|
+
"aria-label": ariaLabel
|
|
2644
|
+
}) {
|
|
2645
|
+
const { id, open, orientation, toggle } = useAccordionSection();
|
|
2646
|
+
const state = { id, open, orientation, toggle };
|
|
2647
|
+
if (children !== void 0) {
|
|
2648
|
+
return /* @__PURE__ */ jsx(
|
|
2649
|
+
"div",
|
|
2650
|
+
{
|
|
2651
|
+
"data-react-fancy-accordion-trigger": "",
|
|
2652
|
+
"data-state": open ? "open" : "closed",
|
|
2653
|
+
"data-orientation": orientation,
|
|
2654
|
+
className,
|
|
2655
|
+
children: renderSlot(children, state)
|
|
2656
|
+
}
|
|
2657
|
+
);
|
|
2658
|
+
}
|
|
2659
|
+
if (open) {
|
|
2660
|
+
return /* @__PURE__ */ jsx(
|
|
2661
|
+
"button",
|
|
2662
|
+
{
|
|
2663
|
+
type: "button",
|
|
2664
|
+
onClick: toggle,
|
|
2665
|
+
"aria-label": ariaLabel ?? "Collapse section",
|
|
2666
|
+
"data-react-fancy-accordion-trigger": "",
|
|
2667
|
+
"data-state": "open",
|
|
2668
|
+
"data-orientation": orientation,
|
|
2669
|
+
className: cn(
|
|
2670
|
+
"group relative flex shrink-0 items-center justify-center cursor-pointer",
|
|
2671
|
+
"text-zinc-500 dark:text-zinc-500",
|
|
2672
|
+
"hover:text-zinc-900 dark:hover:text-zinc-100",
|
|
2673
|
+
orientation === "horizontal" ? "w-px self-stretch hover:w-3 mx-1" : "h-px self-stretch hover:h-3 my-1",
|
|
2674
|
+
"before:absolute before:inset-0 before:bg-zinc-200 dark:before:bg-zinc-700",
|
|
2675
|
+
orientation === "horizontal" ? "before:w-px before:left-1/2 before:-translate-x-1/2" : "before:h-px before:top-1/2 before:-translate-y-1/2",
|
|
2676
|
+
"transition-all duration-150",
|
|
2677
|
+
className
|
|
2678
|
+
),
|
|
2679
|
+
children: /* @__PURE__ */ jsx(
|
|
2680
|
+
ChevronIcon,
|
|
2681
|
+
{
|
|
2682
|
+
orientation,
|
|
2683
|
+
purpose: "collapse",
|
|
2684
|
+
className: "relative opacity-0 group-hover:opacity-100 transition-opacity"
|
|
2685
|
+
}
|
|
2686
|
+
)
|
|
2687
|
+
}
|
|
2688
|
+
);
|
|
2689
|
+
}
|
|
2690
|
+
return /* @__PURE__ */ jsx(
|
|
2691
|
+
"button",
|
|
2692
|
+
{
|
|
2693
|
+
type: "button",
|
|
2694
|
+
onClick: toggle,
|
|
2695
|
+
"aria-label": ariaLabel ?? "Expand section",
|
|
2696
|
+
"data-react-fancy-accordion-trigger": "",
|
|
2697
|
+
"data-state": "closed",
|
|
2698
|
+
"data-orientation": orientation,
|
|
2699
|
+
className: cn(
|
|
2700
|
+
"flex shrink-0 items-center justify-center rounded-md",
|
|
2701
|
+
"text-zinc-400 dark:text-zinc-500",
|
|
2702
|
+
"hover:text-zinc-900 dark:hover:text-zinc-100",
|
|
2703
|
+
"hover:bg-zinc-100 dark:hover:bg-zinc-800",
|
|
2704
|
+
"transition-colors cursor-pointer",
|
|
2705
|
+
orientation === "horizontal" ? "h-8 w-6 mx-0.5" : "w-8 h-6 my-0.5",
|
|
2706
|
+
className
|
|
2707
|
+
),
|
|
2708
|
+
children: /* @__PURE__ */ jsx(ChevronIcon, { orientation, purpose: "expand" })
|
|
2709
|
+
}
|
|
2710
|
+
);
|
|
2711
|
+
}
|
|
2712
|
+
AccordionPanelTrigger.displayName = "AccordionPanelTrigger";
|
|
2713
|
+
function ChevronIcon({
|
|
2714
|
+
orientation,
|
|
2715
|
+
purpose,
|
|
2716
|
+
className
|
|
2717
|
+
}) {
|
|
2718
|
+
const transform = orientation === "horizontal" ? "rotate(180deg)" : purpose === "expand" ? "rotate(90deg)" : "rotate(270deg)";
|
|
2719
|
+
return /* @__PURE__ */ jsx(
|
|
2720
|
+
"svg",
|
|
2721
|
+
{
|
|
2722
|
+
viewBox: "0 0 16 16",
|
|
2723
|
+
width: "12",
|
|
2724
|
+
height: "12",
|
|
2725
|
+
fill: "none",
|
|
2726
|
+
stroke: "currentColor",
|
|
2727
|
+
strokeWidth: "2",
|
|
2728
|
+
strokeLinecap: "round",
|
|
2729
|
+
strokeLinejoin: "round",
|
|
2730
|
+
style: { transform },
|
|
2731
|
+
className,
|
|
2732
|
+
"aria-hidden": "true",
|
|
2733
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "6 4 10 8 6 12" })
|
|
2734
|
+
}
|
|
2735
|
+
);
|
|
2736
|
+
}
|
|
2737
|
+
function AccordionPanelContent({
|
|
2738
|
+
children,
|
|
2739
|
+
className
|
|
2740
|
+
}) {
|
|
2741
|
+
const { open, orientation } = useAccordionSection();
|
|
2742
|
+
if (!open) return null;
|
|
2743
|
+
return /* @__PURE__ */ jsx(
|
|
2744
|
+
"div",
|
|
2745
|
+
{
|
|
2746
|
+
"data-react-fancy-accordion-content": "",
|
|
2747
|
+
"data-orientation": orientation,
|
|
2748
|
+
className: cn(
|
|
2749
|
+
"flex items-center gap-1",
|
|
2750
|
+
orientation === "horizontal" ? "flex-row" : "flex-col",
|
|
2751
|
+
className
|
|
2752
|
+
),
|
|
2753
|
+
children
|
|
2754
|
+
}
|
|
2755
|
+
);
|
|
2756
|
+
}
|
|
2757
|
+
AccordionPanelContent.displayName = "AccordionPanelContent";
|
|
2758
|
+
function AccordionPanelRoot({
|
|
2759
|
+
orientation = "horizontal",
|
|
2760
|
+
value: controlledValue,
|
|
2761
|
+
defaultValue,
|
|
2762
|
+
onValueChange,
|
|
2763
|
+
className,
|
|
2764
|
+
children
|
|
2765
|
+
}) {
|
|
2766
|
+
const [openIds, setOpenIds] = useControllableState(
|
|
2767
|
+
controlledValue,
|
|
2768
|
+
defaultValue ?? [],
|
|
2769
|
+
onValueChange
|
|
2770
|
+
);
|
|
2771
|
+
const openSet = useMemo(() => new Set(openIds), [openIds]);
|
|
2772
|
+
const isOpen = useCallback((id) => openSet.has(id), [openSet]);
|
|
2773
|
+
const open = useCallback(
|
|
2774
|
+
(id) => {
|
|
2775
|
+
setOpenIds(openSet.has(id) ? openIds ?? [] : [...openIds ?? [], id]);
|
|
2776
|
+
},
|
|
2777
|
+
[openSet, openIds, setOpenIds]
|
|
2778
|
+
);
|
|
2779
|
+
const close = useCallback(
|
|
2780
|
+
(id) => {
|
|
2781
|
+
setOpenIds((openIds ?? []).filter((x) => x !== id));
|
|
2782
|
+
},
|
|
2783
|
+
[openIds, setOpenIds]
|
|
2784
|
+
);
|
|
2785
|
+
const toggle = useCallback(
|
|
2786
|
+
(id) => {
|
|
2787
|
+
setOpenIds(
|
|
2788
|
+
openSet.has(id) ? (openIds ?? []).filter((x) => x !== id) : [...openIds ?? [], id]
|
|
2789
|
+
);
|
|
2790
|
+
},
|
|
2791
|
+
[openSet, openIds, setOpenIds]
|
|
2792
|
+
);
|
|
2793
|
+
const [sectionIds, setSectionIds] = useState([]);
|
|
2794
|
+
const orderRef = useRef([]);
|
|
2795
|
+
const registerSection = useCallback((id) => {
|
|
2796
|
+
if (!orderRef.current.includes(id)) {
|
|
2797
|
+
orderRef.current = [...orderRef.current, id];
|
|
2798
|
+
setSectionIds(orderRef.current);
|
|
2799
|
+
}
|
|
2800
|
+
return () => {
|
|
2801
|
+
orderRef.current = orderRef.current.filter((x) => x !== id);
|
|
2802
|
+
setSectionIds(orderRef.current);
|
|
2803
|
+
};
|
|
2804
|
+
}, []);
|
|
2805
|
+
const ctx = useMemo(
|
|
2806
|
+
() => ({
|
|
2807
|
+
orientation,
|
|
2808
|
+
isOpen,
|
|
2809
|
+
toggle,
|
|
2810
|
+
open,
|
|
2811
|
+
close,
|
|
2812
|
+
sectionIds,
|
|
2813
|
+
registerSection
|
|
2814
|
+
}),
|
|
2815
|
+
[orientation, isOpen, toggle, open, close, sectionIds, registerSection]
|
|
2816
|
+
);
|
|
2817
|
+
return /* @__PURE__ */ jsx(AccordionPanelContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
|
|
2818
|
+
"div",
|
|
2819
|
+
{
|
|
2820
|
+
"data-react-fancy-accordion-panel": "",
|
|
2821
|
+
"data-orientation": orientation,
|
|
2822
|
+
className: cn(
|
|
2823
|
+
"inline-flex items-stretch",
|
|
2824
|
+
orientation === "horizontal" ? "flex-row" : "flex-col",
|
|
2825
|
+
className
|
|
2826
|
+
),
|
|
2827
|
+
children
|
|
2828
|
+
}
|
|
2829
|
+
) });
|
|
2830
|
+
}
|
|
2831
|
+
AccordionPanelRoot.displayName = "AccordionPanel";
|
|
2832
|
+
var AccordionPanel = AccordionPanelRoot;
|
|
2833
|
+
AccordionPanel.Section = AccordionPanelSection;
|
|
2834
|
+
AccordionPanel.Trigger = AccordionPanelTrigger;
|
|
2835
|
+
AccordionPanel.Content = AccordionPanelContent;
|
|
2484
2836
|
|
|
2485
2837
|
// src/components/inputs/inputs.utils.ts
|
|
2486
2838
|
var inputSizeClasses = {
|
|
@@ -3367,24 +3719,6 @@ var Select = forwardRef(
|
|
|
3367
3719
|
}
|
|
3368
3720
|
);
|
|
3369
3721
|
Select.displayName = "Select";
|
|
3370
|
-
function useControllableState(controlledValue, defaultValue, onChange) {
|
|
3371
|
-
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
|
|
3372
|
-
const isControlled = controlledValue !== void 0;
|
|
3373
|
-
const value = isControlled ? controlledValue : uncontrolledValue;
|
|
3374
|
-
const onChangeRef = useRef(onChange);
|
|
3375
|
-
onChangeRef.current = onChange;
|
|
3376
|
-
const setValue = useCallback(
|
|
3377
|
-
(next) => {
|
|
3378
|
-
const nextValue = typeof next === "function" ? next(value) : next;
|
|
3379
|
-
if (!isControlled) {
|
|
3380
|
-
setUncontrolledValue(nextValue);
|
|
3381
|
-
}
|
|
3382
|
-
onChangeRef.current?.(nextValue);
|
|
3383
|
-
},
|
|
3384
|
-
[isControlled, value]
|
|
3385
|
-
);
|
|
3386
|
-
return [value, setValue];
|
|
3387
|
-
}
|
|
3388
3722
|
var Checkbox = forwardRef(
|
|
3389
3723
|
({
|
|
3390
3724
|
size = "md",
|
|
@@ -10077,13 +10411,15 @@ function mergeExtensions(instanceExtensions) {
|
|
|
10077
10411
|
}
|
|
10078
10412
|
return merged;
|
|
10079
10413
|
}
|
|
10080
|
-
function toHtml(value, outputFormat) {
|
|
10414
|
+
function toHtml(value, outputFormat, unsafe) {
|
|
10081
10415
|
if (!value) return "";
|
|
10082
|
-
|
|
10083
|
-
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
|
|
10416
|
+
const raw = (() => {
|
|
10417
|
+
if (outputFormat === "html") return value;
|
|
10418
|
+
const format = detectFormat(value);
|
|
10419
|
+
if (format === "html") return value;
|
|
10420
|
+
return marked.parse(value, { async: false }).trim();
|
|
10421
|
+
})();
|
|
10422
|
+
return unsafe ? raw : sanitizeHtml(raw);
|
|
10087
10423
|
}
|
|
10088
10424
|
function EditorRoot({
|
|
10089
10425
|
children,
|
|
@@ -10094,12 +10430,13 @@ function EditorRoot({
|
|
|
10094
10430
|
outputFormat = "html",
|
|
10095
10431
|
lineSpacing = 1.6,
|
|
10096
10432
|
placeholder,
|
|
10097
|
-
extensions: instanceExtensions
|
|
10433
|
+
extensions: instanceExtensions,
|
|
10434
|
+
unsafe = false
|
|
10098
10435
|
}) {
|
|
10099
10436
|
const contentRef = useRef(null);
|
|
10100
10437
|
const [, setValue] = useControllableState(controlledValue, defaultValue, onChange);
|
|
10101
10438
|
const initialHtml = useMemo(
|
|
10102
|
-
() => toHtml(controlledValue ?? defaultValue, outputFormat),
|
|
10439
|
+
() => toHtml(controlledValue ?? defaultValue, outputFormat, unsafe),
|
|
10103
10440
|
// Only compute once on mount — don't re-run when value changes from user input
|
|
10104
10441
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
10105
10442
|
[]
|
|
@@ -10184,7 +10521,11 @@ var Editor = Object.assign(EditorRoot, {
|
|
|
10184
10521
|
Toolbar: ToolbarWithSeparator,
|
|
10185
10522
|
Content: EditorContent
|
|
10186
10523
|
});
|
|
10187
|
-
function RenderedContent({
|
|
10524
|
+
function RenderedContent({
|
|
10525
|
+
html,
|
|
10526
|
+
extensions: instanceExtensions,
|
|
10527
|
+
unsafe = false
|
|
10528
|
+
}) {
|
|
10188
10529
|
const extensions = useMemo(
|
|
10189
10530
|
() => mergeExtensions(instanceExtensions),
|
|
10190
10531
|
[instanceExtensions]
|
|
@@ -10193,15 +10534,16 @@ function RenderedContent({ html, extensions: instanceExtensions }) {
|
|
|
10193
10534
|
() => parseSegments(html, extensions),
|
|
10194
10535
|
[html, extensions]
|
|
10195
10536
|
);
|
|
10537
|
+
const renderHtml = (content) => unsafe ? content : sanitizeHtml(content);
|
|
10196
10538
|
if (segments.length === 1 && segments[0].type === "html") {
|
|
10197
|
-
return /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: segments[0].content } });
|
|
10539
|
+
return /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: renderHtml(segments[0].content) } });
|
|
10198
10540
|
}
|
|
10199
10541
|
if (segments.length === 0) {
|
|
10200
10542
|
return null;
|
|
10201
10543
|
}
|
|
10202
10544
|
return /* @__PURE__ */ jsx(Fragment, { children: segments.map((segment, i) => {
|
|
10203
10545
|
if (segment.type === "html") {
|
|
10204
|
-
return segment.content ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: segment.content } }, i) : null;
|
|
10546
|
+
return segment.content ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: renderHtml(segment.content) } }, i) : null;
|
|
10205
10547
|
}
|
|
10206
10548
|
const ext = extensions.find(
|
|
10207
10549
|
(e) => e.tag.toLowerCase() === segment.tag
|
|
@@ -10219,7 +10561,8 @@ function ContentRenderer({
|
|
|
10219
10561
|
format = "auto",
|
|
10220
10562
|
lineSpacing = 1.6,
|
|
10221
10563
|
className,
|
|
10222
|
-
extensions: instanceExtensions
|
|
10564
|
+
extensions: instanceExtensions,
|
|
10565
|
+
unsafe = false
|
|
10223
10566
|
}) {
|
|
10224
10567
|
const extensions = useMemo(
|
|
10225
10568
|
() => mergeExtensions(instanceExtensions),
|
|
@@ -10227,11 +10570,9 @@ function ContentRenderer({
|
|
|
10227
10570
|
);
|
|
10228
10571
|
const html = useMemo(() => {
|
|
10229
10572
|
const resolvedFormat = format === "auto" ? detectFormat(value) : format;
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
return value;
|
|
10234
|
-
}, [value, format]);
|
|
10573
|
+
const raw = resolvedFormat === "markdown" ? marked.parse(value, { async: false }) : value;
|
|
10574
|
+
return unsafe ? raw : sanitizeHtml(raw);
|
|
10575
|
+
}, [value, format, unsafe]);
|
|
10235
10576
|
const hasExtensions = extensions.length > 0;
|
|
10236
10577
|
return /* @__PURE__ */ jsx(
|
|
10237
10578
|
"div",
|
|
@@ -10239,7 +10580,7 @@ function ContentRenderer({
|
|
|
10239
10580
|
"data-react-fancy-content-renderer": "",
|
|
10240
10581
|
style: { lineHeight: lineSpacing },
|
|
10241
10582
|
className: cn("text-sm", proseClasses, className),
|
|
10242
|
-
children: hasExtensions ? /* @__PURE__ */ jsx(RenderedContent, { html, extensions }) : /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: html } })
|
|
10583
|
+
children: hasExtensions ? /* @__PURE__ */ jsx(RenderedContent, { html, extensions, unsafe }) : /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: html } })
|
|
10243
10584
|
}
|
|
10244
10585
|
);
|
|
10245
10586
|
}
|
|
@@ -11511,7 +11852,7 @@ function DiagramToolbar({ className }) {
|
|
|
11511
11852
|
const canImport = importableRef.current;
|
|
11512
11853
|
const handleDownload = useCallback(
|
|
11513
11854
|
async (format) => {
|
|
11514
|
-
const { serializeToERD, serializeToUML, serializeToDFD } = await import('./diagram.serializers-
|
|
11855
|
+
const { serializeToERD, serializeToUML, serializeToDFD } = await import('./diagram.serializers-6RPUO46U.js');
|
|
11515
11856
|
let content;
|
|
11516
11857
|
switch (format) {
|
|
11517
11858
|
case "erd":
|
|
@@ -11542,7 +11883,7 @@ function DiagramToolbar({ className }) {
|
|
|
11542
11883
|
if (!file || !onImport) return;
|
|
11543
11884
|
const text = await file.text();
|
|
11544
11885
|
const ext = file.name.split(".").pop()?.toLowerCase();
|
|
11545
|
-
const { deserializeSchema } = await import('./diagram.serializers-
|
|
11886
|
+
const { deserializeSchema } = await import('./diagram.serializers-6RPUO46U.js');
|
|
11546
11887
|
let format = "erd";
|
|
11547
11888
|
if (ext === "puml" || ext === "uml") format = "uml";
|
|
11548
11889
|
else if (ext === "dfd") format = "dfd";
|
|
@@ -11610,9 +11951,12 @@ var VERTICAL_GAP = 60;
|
|
|
11610
11951
|
function getEntityHeight(fieldCount) {
|
|
11611
11952
|
return HEADER_HEIGHT2 + Math.max(fieldCount, 1) * FIELD_HEIGHT2;
|
|
11612
11953
|
}
|
|
11954
|
+
function resolveEntityId(entity) {
|
|
11955
|
+
return entity.id ?? entity.name;
|
|
11956
|
+
}
|
|
11613
11957
|
function computeDiagramLayout(schema) {
|
|
11614
11958
|
const positions = /* @__PURE__ */ new Map();
|
|
11615
|
-
const entityIds = new Set(schema.entities.map(
|
|
11959
|
+
const entityIds = new Set(schema.entities.map(resolveEntityId));
|
|
11616
11960
|
const incoming = /* @__PURE__ */ new Map();
|
|
11617
11961
|
for (const id of entityIds) {
|
|
11618
11962
|
incoming.set(id, /* @__PURE__ */ new Set());
|
|
@@ -11633,7 +11977,7 @@ function computeDiagramLayout(schema) {
|
|
|
11633
11977
|
}
|
|
11634
11978
|
}
|
|
11635
11979
|
if (queue.length === 0 && entityIds.size > 0) {
|
|
11636
|
-
const firstId = schema.entities[0]
|
|
11980
|
+
const firstId = resolveEntityId(schema.entities[0]);
|
|
11637
11981
|
rowAssignment.set(firstId, 0);
|
|
11638
11982
|
assigned.add(firstId);
|
|
11639
11983
|
queue.push(firstId);
|
|
@@ -11673,7 +12017,7 @@ function computeDiagramLayout(schema) {
|
|
|
11673
12017
|
}
|
|
11674
12018
|
const fieldCounts = /* @__PURE__ */ new Map();
|
|
11675
12019
|
for (const entity of schema.entities) {
|
|
11676
|
-
fieldCounts.set(entity
|
|
12020
|
+
fieldCounts.set(resolveEntityId(entity), entity.fields?.length ?? 0);
|
|
11677
12021
|
}
|
|
11678
12022
|
const sortedRows = Array.from(rows.keys()).sort((a, b) => a - b);
|
|
11679
12023
|
let currentY = 0;
|
|
@@ -11870,7 +12214,7 @@ function FolderIcon({ open }) {
|
|
|
11870
12214
|
}
|
|
11871
12215
|
return /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", className: "shrink-0", children: /* @__PURE__ */ jsx("path", { d: "M1.5 3a1 1 0 011-1h3l1.5 1.5H13a1 1 0 011 1v8a1 1 0 01-1 1H2.5a1 1 0 01-1-1V3z", fill: "#fbbf24" }) });
|
|
11872
12216
|
}
|
|
11873
|
-
function
|
|
12217
|
+
function ChevronIcon2({ open }) {
|
|
11874
12218
|
return /* @__PURE__ */ jsx(
|
|
11875
12219
|
"svg",
|
|
11876
12220
|
{
|
|
@@ -12052,7 +12396,7 @@ function TreeNode({ node, depth }) {
|
|
|
12052
12396
|
),
|
|
12053
12397
|
style: { paddingLeft },
|
|
12054
12398
|
children: [
|
|
12055
|
-
isFolder && /* @__PURE__ */ jsx(
|
|
12399
|
+
isFolder && /* @__PURE__ */ jsx(ChevronIcon2, { open: isExpanded }),
|
|
12056
12400
|
!isFolder && /* @__PURE__ */ jsx("span", { className: "w-3.5 shrink-0" }),
|
|
12057
12401
|
showIcons && (node.icon ?? (isFolder ? /* @__PURE__ */ jsx(FolderIcon, { open: isExpanded }) : /* @__PURE__ */ jsx(FileIcon, { ext: node.ext ?? node.label.split(".").pop() }))),
|
|
12058
12402
|
/* @__PURE__ */ jsx("span", { className: "truncate", children: node.label })
|
|
@@ -12181,6 +12525,6 @@ var TreeNav = Object.assign(TreeNavRoot, {
|
|
|
12181
12525
|
Node: TreeNode
|
|
12182
12526
|
});
|
|
12183
12527
|
|
|
12184
|
-
export { Accordion, Action, Autocomplete, Avatar, Badge, Brand, Breadcrumbs, Calendar, Callout, Canvas, Card, Carousel, Chart, Checkbox, CheckboxGroup, ColorPicker, Command, Composer, ContentRenderer, ContextMenu, DatePicker, Diagram, Dropdown, EMOJI_CATEGORY_ORDER, EMOJI_DATA, EMOJI_ENTRIES, Editor, Emoji, EmojiSelect, Field, FileUpload, Heading, Icon, Input, Kanban, Menu2 as Menu, MobileMenu, Modal, MultiSwitch, Navbar, OtpInput, Pagination, Pillbox, Popover, Portal, Profile, Progress, RadioGroup, SKIN_TONES, Select, Separator, Sidebar, Skeleton, Slider, Switch, Table, Tabs, Text, Textarea, TimePicker, Timeline, Toast, Tooltip, TreeNav, applyTone, cn, configureIcons, find, hasSkinTones, registerExtension, registerExtensions, registerIconSet, registerIcons, resolve, search, skinTones, useAccordion, useAnimation, useCanvas, useCarousel, useCommand, useContextMenu, useControllableState, useDiagram, useDropdown, useEditor, useEscapeKey, useFileUpload, useFloatingPosition, useFocusTrap, useId12 as useId, useKanban, useMenu, useMobileMenu, useModal, useNavbar, useNodeRegistry, useOutsideClick, usePanZoom, usePopover, useSidebar, useTabs, useToast, useTreeNav };
|
|
12528
|
+
export { Accordion, AccordionPanel, AccordionPanelContent, AccordionPanelSection, AccordionPanelTrigger, Action, Autocomplete, Avatar, Badge, Brand, Breadcrumbs, Calendar, Callout, Canvas, Card, Carousel, Chart, Checkbox, CheckboxGroup, ColorPicker, Command, Composer, ContentRenderer, ContextMenu, DatePicker, Diagram, Dropdown, EMOJI_CATEGORY_ORDER, EMOJI_DATA, EMOJI_ENTRIES, Editor, Emoji, EmojiSelect, Field, FileUpload, Heading, Icon, Input, Kanban, Menu2 as Menu, MobileMenu, Modal, MultiSwitch, Navbar, OtpInput, Pagination, Pillbox, Popover, Portal, Profile, Progress, RadioGroup, SKIN_TONES, Select, Separator, Sidebar, Skeleton, Slider, Switch, Table, Tabs, Text, Textarea, TimePicker, Timeline, Toast, Tooltip, TreeNav, applyTone, cn, configureIcons, find, hasSkinTones, registerExtension, registerExtensions, registerIconSet, registerIcons, resolve, sanitizeHref, sanitizeHtml, search, skinTones, useAccordion, useAccordionPanel, useAccordionSection, useAnimation, useCanvas, useCarousel, useCommand, useContextMenu, useControllableState, useDiagram, useDropdown, useEditor, useEscapeKey, useFileUpload, useFloatingPosition, useFocusTrap, useId12 as useId, useKanban, useMenu, useMobileMenu, useModal, useNavbar, useNodeRegistry, useOutsideClick, usePanZoom, usePopover, useSidebar, useTabs, useToast, useTreeNav };
|
|
12185
12529
|
//# sourceMappingURL=index.js.map
|
|
12186
12530
|
//# sourceMappingURL=index.js.map
|