neogestify-ui-components 2.1.0 → 2.2.1

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.
Files changed (29) hide show
  1. package/README.md +46 -1
  2. package/dist/components/ElementLibraryBuilder/index.d.mts +5 -0
  3. package/dist/components/ElementLibraryBuilder/index.d.ts +5 -0
  4. package/dist/components/ElementLibraryBuilder/index.js +689 -0
  5. package/dist/components/ElementLibraryBuilder/index.js.map +1 -0
  6. package/dist/components/ElementLibraryBuilder/index.mjs +687 -0
  7. package/dist/components/ElementLibraryBuilder/index.mjs.map +1 -0
  8. package/dist/components/VenueMapEditor/index.d.mts +18 -2
  9. package/dist/components/VenueMapEditor/index.d.ts +18 -2
  10. package/dist/components/VenueMapEditor/index.js +75 -3
  11. package/dist/components/VenueMapEditor/index.js.map +1 -1
  12. package/dist/components/VenueMapEditor/index.mjs +75 -4
  13. package/dist/components/VenueMapEditor/index.mjs.map +1 -1
  14. package/dist/index.d.mts +2 -1
  15. package/dist/index.d.ts +2 -1
  16. package/dist/index.js +468 -3
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +467 -4
  19. package/dist/index.mjs.map +1 -1
  20. package/package.json +1 -1
  21. package/src/components/ElementLibraryBuilder/builder.tsx +400 -0
  22. package/src/components/ElementLibraryBuilder/index.ts +1 -0
  23. package/src/components/VenueMapEditor/components/ElementNode.tsx +22 -0
  24. package/src/components/VenueMapEditor/components/PropertiesPanel.tsx +17 -4
  25. package/src/components/VenueMapEditor/components/Toolbar.tsx +14 -4
  26. package/src/components/VenueMapEditor/index.ts +2 -0
  27. package/src/components/VenueMapEditor/types.ts +11 -1
  28. package/src/components/VenueMapEditor/utils/svgParser.ts +33 -0
  29. package/src/index.ts +1 -0
@@ -91,6 +91,26 @@ function IconUpload({ className }) {
91
91
  function IconLayers({ className }) {
92
92
  return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", className, fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M8.235 1.559a.5.5 0 0 0-.47 0l-7.5 4a.5.5 0 0 0 0 .882L3.188 8 .265 9.559a.5.5 0 0 0 0 .882l7.5 4a.5.5 0 0 0 .47 0l7.5-4a.5.5 0 0 0 0-.882L12.813 8l2.922-1.559a.5.5 0 0 0 0-.882l-7.5-4zm3.515 7.008L14.438 10 8 13.433 1.562 10 4.25 8.567l3.515 1.874a.5.5 0 0 0 .47 0l3.515-1.874zM8 9.433 1.562 6 8 2.567 14.438 6 8 9.433z" }) });
93
93
  }
94
+
95
+ // src/components/VenueMapEditor/utils/svgParser.ts
96
+ var DANGEROUS_TAGS = /\b(script|iframe|object|embed|link|style|meta)\b/gi;
97
+ var DANGEROUS_ATTRS = /\bon\w+\s*=/gi;
98
+ var DANGEROUS_HREF = /\bhref\s*=\s*["']?\s*javascript:/gi;
99
+ var DANGEROUS_XLINK = /\bxlink:href\s*=\s*["']?\s*javascript:/gi;
100
+ function sanitize(html) {
101
+ return html.replace(DANGEROUS_TAGS, "").replace(DANGEROUS_ATTRS, "").replace(DANGEROUS_HREF, "").replace(DANGEROUS_XLINK, "");
102
+ }
103
+ var VIEWBOX_RE = /viewBox\s*=\s*"([^"]+)"/i;
104
+ var SVG_OPEN_END_RE = /<svg[^>]*>/i;
105
+ function parseSvgMarkup(markup) {
106
+ const viewBoxMatch = markup.match(VIEWBOX_RE);
107
+ const viewBox = viewBoxMatch?.[1] ?? "0 0 100 100";
108
+ const svgOpenMatch = markup.match(SVG_OPEN_END_RE);
109
+ const afterOpen = svgOpenMatch ? markup.slice(svgOpenMatch.index + svgOpenMatch[0].length) : markup;
110
+ const closeIdx = afterOpen.lastIndexOf("</svg>");
111
+ const inner = closeIdx >= 0 ? afterOpen.slice(0, closeIdx) : afterOpen;
112
+ return { viewBox, innerHtml: sanitize(inner) };
113
+ }
94
114
  function ToolButton({ active, disabled, title, onClick, children }) {
95
115
  return /* @__PURE__ */ jsx(
96
116
  "button",
@@ -120,7 +140,15 @@ function TypeChip({ typeDef, active, onClick }) {
120
140
  active ? "border-blue-400 bg-blue-50 text-blue-700 font-medium" : "border-slate-200 bg-white text-slate-600 hover:border-slate-300 hover:bg-slate-50"
121
141
  ].join(" "),
122
142
  children: [
123
- /* @__PURE__ */ jsx(
143
+ typeDef.shape === "svg" && typeDef.svgMarkup ? /* @__PURE__ */ jsx(
144
+ "svg",
145
+ {
146
+ viewBox: parseSvgMarkup(typeDef.svgMarkup).viewBox,
147
+ className: "w-2.5 h-2.5 shrink-0",
148
+ style: { color: typeDef.strokeColor },
149
+ dangerouslySetInnerHTML: { __html: parseSvgMarkup(typeDef.svgMarkup).innerHtml }
150
+ }
151
+ ) : /* @__PURE__ */ jsx(
124
152
  "span",
125
153
  {
126
154
  className: "w-2.5 h-2.5 rounded-sm shrink-0",
@@ -1189,6 +1217,28 @@ function ElementNode({
1189
1217
  onClick: handleBodyClick
1190
1218
  }
1191
1219
  ) }),
1220
+ typeDef.shape === "svg" && typeDef.svgMarkup && (() => {
1221
+ const parsed = parseSvgMarkup(typeDef.svgMarkup);
1222
+ const parts = parsed.viewBox.split(/[\s,]+/).map(Number);
1223
+ const vw = parts[2] ?? 100;
1224
+ const vh = parts[3] ?? 100;
1225
+ const sx = vw > 0 ? w / vw : 1;
1226
+ const sy = vh > 0 ? h / vh : 1;
1227
+ const avgScale = Math.sqrt(Math.abs(sx * sy)) || 1;
1228
+ return /* @__PURE__ */ jsx(
1229
+ "g",
1230
+ {
1231
+ transform: `translate(${x}, ${y}) scale(${sx}, ${sy})`,
1232
+ fill: fillColor,
1233
+ stroke: isSelected ? "#3b82f6" : typeDef.strokeColor,
1234
+ strokeWidth: isSelected ? sw / avgScale * 1.5 : sw / avgScale,
1235
+ style: { cursor: bodyCursor },
1236
+ onMouseDown: tool === "SELECT" && !onViewerClick ? handleBodyDown : void 0,
1237
+ onClick: handleBodyClick,
1238
+ dangerouslySetInnerHTML: { __html: parsed.innerHtml }
1239
+ }
1240
+ );
1241
+ })(),
1192
1242
  (element.label ?? typeDef.label) && /* @__PURE__ */ jsx(
1193
1243
  "text",
1194
1244
  {
@@ -1687,14 +1737,35 @@ function PropertiesPanel({
1687
1737
  /* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-b border-slate-100 text-xs font-semibold text-slate-500 uppercase tracking-wide", children: "Propiedades" }),
1688
1738
  /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col gap-4 p-3", children: [
1689
1739
  typeDef && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1690
- /* @__PURE__ */ jsx(
1740
+ typeDef.shape === "svg" ? /* @__PURE__ */ jsx(
1741
+ "svg",
1742
+ {
1743
+ viewBox: (() => {
1744
+ try {
1745
+ return typeDef.svgMarkup ? parseSvgMarkup(typeDef.svgMarkup).viewBox : "0 0 100 100";
1746
+ } catch {
1747
+ return "0 0 100 100";
1748
+ }
1749
+ })(),
1750
+ className: "w-3.5 h-3.5 shrink-0 border border-slate-300 rounded-sm",
1751
+ style: { color: typeDef.strokeColor },
1752
+ dangerouslySetInnerHTML: { __html: (() => {
1753
+ try {
1754
+ return typeDef.svgMarkup ? parseSvgMarkup(typeDef.svgMarkup).innerHtml : "";
1755
+ } catch {
1756
+ return "";
1757
+ }
1758
+ })() }
1759
+ }
1760
+ ) : /* @__PURE__ */ jsx(
1691
1761
  "span",
1692
1762
  {
1693
1763
  className: "w-3.5 h-3.5 rounded-sm shrink-0 border",
1694
1764
  style: { background: typeDef.color, borderColor: typeDef.strokeColor }
1695
1765
  }
1696
1766
  ),
1697
- /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-slate-700 truncate", children: typeDef.label })
1767
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-slate-700 truncate", children: typeDef.label }),
1768
+ typeDef.shape === "svg" && /* @__PURE__ */ jsx("span", { className: "text-[9px] uppercase tracking-wide text-slate-400 font-medium ml-auto", children: "SVG" })
1698
1769
  ] }),
1699
1770
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-0.5", children: [
1700
1771
  /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-slate-400 uppercase tracking-wide", children: "Etiqueta" }),
@@ -2763,6 +2834,6 @@ function VenueMapViewer({ elementStatus, onElementClick, ...rest }) {
2763
2834
  );
2764
2835
  }
2765
2836
 
2766
- export { VenueMapEditor, VenueMapViewer, findNearestNode, genId, snapPoint, snapToGrid, useLibraryStorage, usePanZoom };
2837
+ export { VenueMapEditor, VenueMapViewer, findNearestNode, genId, parseSvgMarkup, snapPoint, snapToGrid, useLibraryStorage, usePanZoom };
2767
2838
  //# sourceMappingURL=index.mjs.map
2768
2839
  //# sourceMappingURL=index.mjs.map