@weaverse/react 0.6.29 → 0.7.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,949 @@
1
+ // src/context.ts
2
+ import { Weaverse } from "@weaverse/core";
3
+ import { createContext as createContext3 } from "react";
4
+
5
+ // src/elements/button.tsx
6
+ import * as React from "react";
7
+ var Button = React.forwardRef((props, ref) => {
8
+ let { openInNewTab, target, value, ...rest } = props;
9
+ if (target) {
10
+ return /* @__PURE__ */ React.createElement("a", {
11
+ href: target,
12
+ target: openInNewTab ? "_blank" : "_self",
13
+ rel: "noreferrer",
14
+ ...rest,
15
+ ref
16
+ }, value);
17
+ }
18
+ return /* @__PURE__ */ React.createElement("button", {
19
+ ref,
20
+ ...rest
21
+ }, value);
22
+ });
23
+ Button.defaultProps = {
24
+ value: "Shop now",
25
+ openInNewTab: false,
26
+ target: "",
27
+ type: "button",
28
+ css: {
29
+ "@desktop": {
30
+ borderRadius: "72px",
31
+ border: "none",
32
+ backgroundColor: "#0F71FF",
33
+ color: "#fff",
34
+ fontSize: "13px",
35
+ padding: "10px 20px"
36
+ }
37
+ }
38
+ };
39
+ var button_default = Button;
40
+
41
+ // src/elements/container.tsx
42
+ import React2, { forwardRef as forwardRef2 } from "react";
43
+ var Container = forwardRef2(
44
+ (props, ref) => {
45
+ let { children, ...rest } = props;
46
+ return /* @__PURE__ */ React2.createElement("div", {
47
+ ref,
48
+ ...rest
49
+ }, children);
50
+ }
51
+ );
52
+ Container.defaultProps = {
53
+ css: {
54
+ "@desktop": {
55
+ alignItems: "flex-start",
56
+ backgroundColor: "rgba(248,203,203,0.38)",
57
+ display: "flex",
58
+ flexDirection: "column",
59
+ gridArea: "1 / 1 / 3 / 6",
60
+ height: "fit-content",
61
+ justifyContent: "flex-start",
62
+ overflow: "hidden",
63
+ textAlign: "left",
64
+ width: "100%"
65
+ }
66
+ }
67
+ };
68
+ var container_default = Container;
69
+
70
+ // src/elements/countdown/index.tsx
71
+ import React4, { forwardRef as forwardRef3, useContext, useEffect } from "react";
72
+
73
+ // src/elements/countdown/timer-block.tsx
74
+ import React3 from "react";
75
+ function TimerBlock({ value, label }) {
76
+ return /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement("div", {
77
+ className: "wv-countdown-number"
78
+ }, value.toString().padStart(2, "0")), label && /* @__PURE__ */ React3.createElement("div", {
79
+ className: "wv-countdown-label"
80
+ }, label));
81
+ }
82
+
83
+ // src/elements/countdown/utils.ts
84
+ var times = ["days", "hours", "minutes", "seconds"];
85
+ function getTime(_seconds) {
86
+ const ONE_MINUTE = 60 * 1e3;
87
+ const ONE_HOUR = 60 * ONE_MINUTE;
88
+ const ONE_DAY = 24 * ONE_HOUR;
89
+ const days = Math.floor(_seconds / ONE_DAY);
90
+ const hours = Math.floor((_seconds - days * ONE_DAY) / ONE_HOUR);
91
+ const minutes = Math.floor(
92
+ (_seconds - days * ONE_DAY - hours * ONE_HOUR) / ONE_MINUTE
93
+ );
94
+ const seconds = Math.floor(
95
+ (_seconds - days * ONE_DAY - hours * ONE_HOUR - minutes * ONE_MINUTE) / 1e3
96
+ );
97
+ return { days, hours, minutes, seconds };
98
+ }
99
+
100
+ // src/elements/countdown/index.tsx
101
+ var Countdown = forwardRef3(
102
+ (props, ref) => {
103
+ const { isDesignMode } = useContext(WeaverseContext);
104
+ let {
105
+ timerType,
106
+ startTime,
107
+ endTime,
108
+ periods,
109
+ redirectUrl,
110
+ openInNewTab,
111
+ showColon,
112
+ showLabel,
113
+ ...rest
114
+ } = props;
115
+ const [remaining, setRemaining] = React4.useState(0);
116
+ if (typeof endTime !== "number") {
117
+ endTime = Number.parseInt(endTime);
118
+ }
119
+ useEffect(() => {
120
+ const flag = setInterval(() => {
121
+ const remainingTime = Math.max(
122
+ (timerType === "fixed-time" ? new Date(endTime).getTime() : new Date(startTime).getTime() + periods * 60 * 1e3) - Date.now(),
123
+ 0
124
+ );
125
+ if (!isDesignMode && redirectUrl && remainingTime > 0 && remainingTime < 1e3) {
126
+ window.open(redirectUrl, openInNewTab ? "_blank" : "_self");
127
+ }
128
+ setRemaining(remainingTime);
129
+ }, 1e3);
130
+ return () => {
131
+ clearInterval(flag);
132
+ };
133
+ }, [startTime, endTime, periods, timerType]);
134
+ const timer = getTime(remaining);
135
+ return /* @__PURE__ */ React4.createElement("div", {
136
+ ref,
137
+ ...rest
138
+ }, times.map((time) => {
139
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, {
140
+ key: time
141
+ }, /* @__PURE__ */ React4.createElement(TimerBlock, {
142
+ label: showLabel ? time : "",
143
+ value: timer[time]
144
+ }), time !== "seconds" && /* @__PURE__ */ React4.createElement("span", {
145
+ className: `wv-countdown-number ${showColon ? "" : "hidden"}`
146
+ }, ":"));
147
+ }));
148
+ }
149
+ );
150
+ Countdown.defaultProps = {
151
+ timerType: "fixed-time",
152
+ startTime: Date.now(),
153
+ endTime: 1661140528e3,
154
+ periods: 90,
155
+ redirectUrl: "https://myshop.com",
156
+ openInNewTab: false,
157
+ showLabel: true,
158
+ showColon: true,
159
+ css: {
160
+ "@desktop": {
161
+ fontFamily: "Inter",
162
+ fontSize: 36,
163
+ fontWeight: 500,
164
+ display: "grid",
165
+ gridAutoFlow: "column",
166
+ gap: 10,
167
+ "& > div": {
168
+ width: 48,
169
+ textAlign: "center"
170
+ },
171
+ ".wv-countdown-label": {
172
+ fontSize: 10
173
+ },
174
+ "& > span": {
175
+ lineHeight: "100%"
176
+ },
177
+ "& .hidden": {
178
+ visibility: "hidden"
179
+ }
180
+ }
181
+ }
182
+ };
183
+ var countdown_default = Countdown;
184
+
185
+ // src/elements/image.tsx
186
+ import React5, { useContext as useContext2 } from "react";
187
+ var Image = React5.forwardRef(
188
+ (props, ref) => {
189
+ let { isDesignMode } = useContext2(WeaverseContext);
190
+ let {
191
+ src,
192
+ alt,
193
+ objectFit,
194
+ objectPosition,
195
+ onClickAction,
196
+ openLinkInNewTab,
197
+ ...rest
198
+ } = props;
199
+ let style = {
200
+ "--wv-img-object-fit": objectFit,
201
+ "--wv-img-object-position": objectPosition
202
+ };
203
+ let handleClick = () => {
204
+ if (isDesignMode) {
205
+ return console.log("Click action:", onClickAction);
206
+ }
207
+ if (onClickAction) {
208
+ console.log("TODO: click action:", onClickAction);
209
+ }
210
+ };
211
+ return /* @__PURE__ */ React5.createElement("div", {
212
+ ref,
213
+ ...rest,
214
+ style,
215
+ onClick: handleClick
216
+ }, /* @__PURE__ */ React5.createElement("img", {
217
+ alt,
218
+ src
219
+ }));
220
+ }
221
+ );
222
+ Image.defaultProps = {
223
+ src: "https://ucarecdn.com/1cdc9d39-ca62-492e-8ec7-f1a86b241a90/",
224
+ alt: "Image alt text",
225
+ objectFit: "cover",
226
+ objectPosition: "center",
227
+ onClickAction: "open-lightbox",
228
+ openLinkInNewTab: false,
229
+ css: {
230
+ "@desktop": {
231
+ img: {
232
+ width: "100%",
233
+ height: "100%",
234
+ objectFit: "var(--wv-img-object-fit, cover)",
235
+ objectPosition: "var(--wv-img-object-position, center)"
236
+ }
237
+ }
238
+ }
239
+ };
240
+ var image_default = Image;
241
+
242
+ // src/elements/layout.tsx
243
+ import React6, { forwardRef as forwardRef4 } from "react";
244
+ var Layout = forwardRef4((props, ref) => {
245
+ let { children, rows, gap, rowSize, columns, gridSize, ...rest } = props;
246
+ let style = {
247
+ "--grid-size": gridSize + "px",
248
+ "--rows": rows,
249
+ "--columns": columns,
250
+ "--gap": gap + "px",
251
+ "--row-size": rowSize + "px",
252
+ "--col-size": "calc((var(--grid-size) - calc(var(--columns) - 1) * var(--gap)) / var(--columns))"
253
+ };
254
+ return /* @__PURE__ */ React6.createElement("section", {
255
+ ref,
256
+ ...rest,
257
+ style
258
+ }, /* @__PURE__ */ React6.createElement("div", {
259
+ "data-layout-content": true
260
+ }, children));
261
+ });
262
+ Layout.defaultProps = {
263
+ gridSize: 1224,
264
+ rows: 12,
265
+ columns: 12,
266
+ gap: 16,
267
+ rowSize: 48,
268
+ css: {
269
+ "@desktop": {
270
+ paddingTop: "16px",
271
+ paddingBottom: "16px",
272
+ paddingLeft: "var(--gap)",
273
+ paddingRight: "var(--gap)",
274
+ "> [data-layout-content]": {
275
+ margin: "0 auto",
276
+ display: "grid !important",
277
+ gridTemplateRows: "repeat(var(--rows), var(--row-size))",
278
+ gridTemplateColumns: "repeat(var(--columns), minmax(0, var(--col-size)))",
279
+ gap: "var(--gap)",
280
+ maxWidth: "var(--grid-size)"
281
+ }
282
+ },
283
+ "@mobile": {
284
+ padding: "0 16px",
285
+ "> [data-layout-content]": {
286
+ display: "flex !important",
287
+ flexDirection: "column"
288
+ }
289
+ }
290
+ }
291
+ };
292
+ var layout_default = Layout;
293
+
294
+ // src/elements/map.tsx
295
+ import React7, { forwardRef as forwardRef5 } from "react";
296
+ var Map = forwardRef5((props, ref) => {
297
+ let { place, zoom, ...rest } = props;
298
+ return /* @__PURE__ */ React7.createElement("div", {
299
+ ref,
300
+ ...rest
301
+ }, /* @__PURE__ */ React7.createElement("iframe", {
302
+ loading: "lazy",
303
+ scrolling: "no",
304
+ width: "100%",
305
+ height: "100%",
306
+ title: "map",
307
+ src: `https://maps.google.com/maps?z=${zoom}&t=m&q=${place}&ie=UTF8&&output=embed`,
308
+ style: { pointerEvents: "none" }
309
+ }));
310
+ });
311
+ Map.defaultProps = {
312
+ place: "Hanoi",
313
+ zoom: 14
314
+ };
315
+ var map_default = Map;
316
+
317
+ // src/elements/text.tsx
318
+ import * as React8 from "react";
319
+ var Text = React8.forwardRef(
320
+ (props, ref) => {
321
+ let { children, value, ...rest } = props;
322
+ return /* @__PURE__ */ React8.createElement("div", {
323
+ ref,
324
+ ...rest,
325
+ dangerouslySetInnerHTML: { __html: value }
326
+ });
327
+ }
328
+ );
329
+ Text.defaultProps = {
330
+ value: "The quick brown fox jumps over the lazy dog",
331
+ css: {
332
+ "@desktop": {
333
+ width: "100%",
334
+ height: "fit-content",
335
+ padding: "20px",
336
+ outline: "none",
337
+ wordBreak: "break-word",
338
+ overflowWrap: "break-word",
339
+ whiteSpace: "break-spaces"
340
+ }
341
+ }
342
+ };
343
+ var text_default = Text;
344
+
345
+ // src/elements/video.tsx
346
+ import React9, { forwardRef as forwardRef7, useContext as useContext3 } from "react";
347
+ var Video = forwardRef7((props, ref) => {
348
+ let { isDesignMode } = useContext3(WeaverseContext);
349
+ let { src, type, controls, poster, autoPlay, loop, muted, ...rest } = props;
350
+ return /* @__PURE__ */ React9.createElement("div", {
351
+ ref,
352
+ ...rest
353
+ }, /* @__PURE__ */ React9.createElement("video", {
354
+ controls: isDesignMode ? false : controls,
355
+ autoPlay: isDesignMode ? false : autoPlay,
356
+ loop,
357
+ muted: true,
358
+ controlsList: "nodownload",
359
+ disablePictureInPicture: true
360
+ }, /* @__PURE__ */ React9.createElement("source", {
361
+ src,
362
+ type: type || "video/mp4"
363
+ }), "Your browser does not support the video tag."));
364
+ });
365
+ Video.defaultProps = {
366
+ src: "https://youtu.be/wM-NT6hcw48",
367
+ poster: "https://ucarecdn.com/48d73272-3fe3-43f6-8b5b-22b68fc5a8c8/section.png",
368
+ loop: false,
369
+ type: "video/mp4",
370
+ controls: false,
371
+ autoPlay: true,
372
+ muted: true,
373
+ css: {
374
+ "@desktop": {
375
+ video: {
376
+ height: "100%",
377
+ width: "100%",
378
+ aspectRatio: "16 / 9"
379
+ }
380
+ }
381
+ }
382
+ };
383
+ var video_default = Video;
384
+
385
+ // src/elements/instagram.tsx
386
+ import React11, { forwardRef as forwardRef9, useEffect as useEffect2, useState } from "react";
387
+
388
+ // src/elements/shared/Placeholder.tsx
389
+ import React10, { forwardRef as forwardRef8 } from "react";
390
+ var Placeholder = forwardRef8(
391
+ (props, ref) => {
392
+ let { element, children, ...rest } = props;
393
+ let style = {
394
+ position: "absolute",
395
+ height: "100%",
396
+ width: "100%",
397
+ display: "flex",
398
+ flexDirection: "column",
399
+ alignItems: "center",
400
+ justifyContent: "center",
401
+ color: "#374151",
402
+ pointerEvents: "none",
403
+ zIndex: 1
404
+ };
405
+ return /* @__PURE__ */ React10.createElement("div", {
406
+ style,
407
+ ref,
408
+ ...rest
409
+ }, /* @__PURE__ */ React10.createElement("div", {
410
+ style: { fontWeight: 600, marginBottom: "10px" }
411
+ }, element), /* @__PURE__ */ React10.createElement("div", null, children));
412
+ }
413
+ );
414
+ var Placeholder_default = Placeholder;
415
+
416
+ // src/elements/instagram.tsx
417
+ var INSTAGRAM_API = "https://graph.instagram.com";
418
+ var Instagram = forwardRef9(
419
+ (props, ref) => {
420
+ let { token, username, numberOfImages, imagesPerRow, gap, ...rest } = props;
421
+ let [media, setMedia] = useState([]);
422
+ let [error, setError] = useState(null);
423
+ useEffect2(() => {
424
+ if (token) {
425
+ let params = new URLSearchParams({
426
+ access_token: token,
427
+ fields: "id,media_type,caption,media_url,permalink"
428
+ });
429
+ fetch(`${INSTAGRAM_API}/me/media?${params.toString()}`).then((res) => res.json()).then((res) => {
430
+ if (res.error) {
431
+ setError(res);
432
+ } else {
433
+ setError(null);
434
+ setMedia([...res.data]);
435
+ }
436
+ }).catch(setError);
437
+ }
438
+ }, [token]);
439
+ if (!token || error) {
440
+ return /* @__PURE__ */ React11.createElement("div", {
441
+ ref,
442
+ ...rest
443
+ }, /* @__PURE__ */ React11.createElement(Placeholder_default, {
444
+ element: "Instagram"
445
+ }, !token ? "Connect your Instagram account to display photos on your site." : "Invalid or expired token!"));
446
+ }
447
+ let style = {
448
+ "--wv-ig-images-per-row": imagesPerRow,
449
+ "--wv-ig-images-gap": gap + "px"
450
+ };
451
+ return /* @__PURE__ */ React11.createElement("div", {
452
+ ref,
453
+ ...rest,
454
+ style
455
+ }, /* @__PURE__ */ React11.createElement("div", {
456
+ className: "wv-ig-media-container"
457
+ }, media.slice(0, numberOfImages).map((item) => {
458
+ let { id, permalink, caption, media_url } = item;
459
+ return /* @__PURE__ */ React11.createElement("a", {
460
+ key: id,
461
+ href: permalink,
462
+ target: "_blank",
463
+ rel: "noreferrer"
464
+ }, /* @__PURE__ */ React11.createElement("img", {
465
+ alt: caption,
466
+ src: media_url
467
+ }));
468
+ })));
469
+ }
470
+ );
471
+ Instagram.defaultProps = {
472
+ token: "",
473
+ username: "",
474
+ numberOfImages: 8,
475
+ imagesPerRow: 4,
476
+ gap: 0,
477
+ css: {
478
+ "@desktop": {
479
+ ".wv-ig-media-container": {
480
+ overflow: "hidden",
481
+ maxWidth: "100%",
482
+ maxHeight: "100%",
483
+ display: "grid",
484
+ gridTemplateColumns: "repeat(var(--wv-ig-images-per-row, 4), 1fr)",
485
+ gap: "var(--wv-ig-images-gap, 0px)",
486
+ img: {
487
+ aspectRatio: "1 / 1",
488
+ width: "100%",
489
+ height: "100%",
490
+ objectFit: "cover"
491
+ }
492
+ }
493
+ }
494
+ }
495
+ };
496
+ var instagram_default = Instagram;
497
+
498
+ // src/elements/accordion/index.tsx
499
+ import React12, { createContext, forwardRef as forwardRef10, useState as useState2 } from "react";
500
+ var AccordionContext = createContext({
501
+ active: null,
502
+ setActive: () => {
503
+ }
504
+ });
505
+ var Accordion = forwardRef10(
506
+ (props, ref) => {
507
+ const { items, children, ...rest } = props;
508
+ const [active, setActive] = useState2(null);
509
+ const setOpenAccordion = (id) => {
510
+ if (id === active) {
511
+ setActive(null);
512
+ } else {
513
+ setActive(id);
514
+ }
515
+ };
516
+ return /* @__PURE__ */ React12.createElement("div", {
517
+ ref,
518
+ ...rest
519
+ }, /* @__PURE__ */ React12.createElement(AccordionContext.Provider, {
520
+ value: { active, setActive: setOpenAccordion }
521
+ }, children));
522
+ }
523
+ );
524
+ Accordion.defaultProps = {
525
+ items: [
526
+ {
527
+ id: 1,
528
+ headerText: "Header 1",
529
+ childrenId: true
530
+ },
531
+ {
532
+ id: 2,
533
+ headerText: "Header 2"
534
+ }
535
+ ],
536
+ css: {
537
+ "@desktop": {
538
+ display: "flex",
539
+ flexDirection: "column",
540
+ gap: 4,
541
+ ".wv-accordion-header": {
542
+ borderRadius: 4,
543
+ padding: 12,
544
+ marginBottom: 4,
545
+ border: "1px solid #76A9FA",
546
+ "&.active": {
547
+ color: "blue"
548
+ },
549
+ '&.active + [data-wv-type="accordion.content"]': {
550
+ maxHeight: "var(--max-height, inherit)"
551
+ }
552
+ }
553
+ }
554
+ }
555
+ };
556
+ var accordion_default = Accordion;
557
+
558
+ // src/elements/accordion/AccordionWrapper.tsx
559
+ import React13, { forwardRef as forwardRef11, useContext as useContext4 } from "react";
560
+ var AccordionWrapper = forwardRef11((props, ref) => {
561
+ const { ["data-wv-id"]: wvId, headerText, children, ...rest } = props;
562
+ const { active, setActive } = useContext4(AccordionContext);
563
+ return /* @__PURE__ */ React13.createElement("div", {
564
+ ref,
565
+ ...rest
566
+ }, /* @__PURE__ */ React13.createElement("div", {
567
+ onClick: () => setActive(wvId),
568
+ className: `wv-accordion-header ${active === wvId ? "active" : ""}`
569
+ }, headerText), children);
570
+ });
571
+ AccordionWrapper.defaultProps = {
572
+ headerText: "Header text",
573
+ css: {
574
+ "@desktop": {
575
+ maxHeight: "100%"
576
+ }
577
+ }
578
+ };
579
+ var AccordionWrapper_default = AccordionWrapper;
580
+
581
+ // src/elements/accordion/AccordionContent.tsx
582
+ import React14, { forwardRef as forwardRef12 } from "react";
583
+ var AccordionContent = forwardRef12((props, ref) => {
584
+ const { rows, columns, gap, rowSize, children, ...rest } = props;
585
+ let style = {
586
+ "--rows": rows,
587
+ "--columns": columns,
588
+ "--gap": gap + "px",
589
+ "--row-size": rowSize + "px",
590
+ "--col-size": "calc((var(--grid-size) - calc(var(--columns) - 1) * var(--gap)) / var(--columns))",
591
+ "--max-height": rows * rowSize + gap * (rowSize - 1) + "px"
592
+ };
593
+ return /* @__PURE__ */ React14.createElement("div", {
594
+ ref,
595
+ ...rest,
596
+ style
597
+ }, React14.Children.count(children) > 0 ? children : /* @__PURE__ */ React14.createElement(Placeholder_default, {
598
+ element: "Accordion"
599
+ }, "Item Content"));
600
+ });
601
+ AccordionContent.defaultProps = {
602
+ rows: 2,
603
+ columns: 12,
604
+ gap: 4,
605
+ rowSize: 48,
606
+ css: {
607
+ "@desktop": {
608
+ width: "100%",
609
+ maxWidth: "var(--grid-size)",
610
+ display: "grid",
611
+ gridTemplateRows: "repeat(var(--rows), var(--row-size))",
612
+ gridTemplateColumns: "repeat(var(--columns), minmax(0, var(--col-size)))",
613
+ gap: "var(--gap)",
614
+ overflow: "hidden",
615
+ maxHeight: 0,
616
+ transition: "all var(--transition-duration, 0.3s) ease-in-out",
617
+ borderRadius: 4
618
+ }
619
+ }
620
+ };
621
+ var AccordionContent_default = AccordionContent;
622
+
623
+ // src/elements/tab/index.tsx
624
+ import React16, { createContext as createContext2, forwardRef as forwardRef13, useState as useState4 } from "react";
625
+
626
+ // src/elements/tab/TabHeaderWrapper.tsx
627
+ import React15, { useContext as useContext5, useEffect as useEffect3, useState as useState3 } from "react";
628
+ function TabHeader(props) {
629
+ const { wvId } = props;
630
+ const { active, setActive } = useContext5(TabContext);
631
+ const { itemInstances } = useContext5(WeaverseContext);
632
+ const instance = itemInstances.get(wvId);
633
+ let [data, setData] = useState3(instance.data);
634
+ useEffect3(() => {
635
+ let update = (data2) => setData({ ...data2 });
636
+ instance.subscribe(update);
637
+ }, []);
638
+ const text = data.headerText;
639
+ return /* @__PURE__ */ React15.createElement("div", {
640
+ onClick: () => setActive(wvId),
641
+ className: `wv-tab-header${active === wvId ? " active" : ""}`
642
+ }, text);
643
+ }
644
+ function TabHeaderWrapper(props) {
645
+ const { itemInstances } = useContext5(WeaverseContext);
646
+ const instance = itemInstances.get(props.wvId);
647
+ const data = instance.data;
648
+ const childIds = data.childIds;
649
+ return /* @__PURE__ */ React15.createElement("div", {
650
+ className: "wv-tab-headerWrapper"
651
+ }, childIds.map((id) => /* @__PURE__ */ React15.createElement(TabHeader, {
652
+ key: id,
653
+ wvId: id
654
+ })));
655
+ }
656
+
657
+ // src/elements/tab/index.tsx
658
+ var TabContext = createContext2({
659
+ active: null,
660
+ setActive: () => {
661
+ }
662
+ });
663
+ var Tab = forwardRef13((props, ref) => {
664
+ var _a, _b, _c;
665
+ const wvId = props["data-wv-id"];
666
+ const { items, children, ...rest } = props;
667
+ const defaultActive = (_c = (_b = (_a = React16.Children.toArray(children)) == null ? void 0 : _a[0]) == null ? void 0 : _b.props) == null ? void 0 : _c.id;
668
+ const [active, setActive] = useState4(defaultActive);
669
+ const setOpenTab = (id) => {
670
+ if (id === active) {
671
+ setActive(null);
672
+ } else {
673
+ setActive(id);
674
+ }
675
+ };
676
+ return /* @__PURE__ */ React16.createElement("div", {
677
+ ref,
678
+ ...rest
679
+ }, /* @__PURE__ */ React16.createElement(TabContext.Provider, {
680
+ value: { active, setActive: setOpenTab }
681
+ }, /* @__PURE__ */ React16.createElement(TabHeaderWrapper, {
682
+ wvId
683
+ }), children));
684
+ });
685
+ Tab.defaultProps = {
686
+ items: [
687
+ {
688
+ headerText: "Header 1"
689
+ },
690
+ {
691
+ headerText: "Header 2"
692
+ },
693
+ {
694
+ headerText: "Header 2"
695
+ }
696
+ ],
697
+ css: {
698
+ "@desktop": {
699
+ display: "flex",
700
+ flexDirection: "column",
701
+ gap: 4,
702
+ "& .wv-tab-headerWrapper": {
703
+ width: "100%",
704
+ display: "flex",
705
+ marginBottom: 10
706
+ },
707
+ "& .wv-tab-header": {
708
+ backgroundColor: "#f0f2f3",
709
+ padding: "10px 16px",
710
+ cursor: "pointer",
711
+ "&.active": {
712
+ backgroundColor: "#0F71FF",
713
+ color: "#fff"
714
+ }
715
+ }
716
+ }
717
+ }
718
+ };
719
+ var tab_default = Tab;
720
+
721
+ // src/elements/tab/TabContent.tsx
722
+ import React17, { forwardRef as forwardRef14, useContext as useContext6 } from "react";
723
+ var TabContent = forwardRef14(
724
+ (props, ref) => {
725
+ const { active } = useContext6(TabContext);
726
+ const wvId = props["data-wv-id"];
727
+ const { rows, columns, gap, rowSize, children, ...rest } = props;
728
+ let style = {
729
+ "--rows": rows,
730
+ "--columns": columns,
731
+ "--gap": gap + "px",
732
+ "--row-size": rowSize + "px",
733
+ "--col-size": "calc((var(--grid-size) - calc(var(--columns) - 1) * var(--gap)) / var(--columns))",
734
+ "--max-height": rows * rowSize + gap * (rowSize - 1) + "px",
735
+ "--content-active": active === wvId ? "grid" : "none"
736
+ };
737
+ return /* @__PURE__ */ React17.createElement("div", {
738
+ ref,
739
+ ...rest,
740
+ style
741
+ }, React17.Children.count(children) > 0 ? children : /* @__PURE__ */ React17.createElement(Placeholder_default, {
742
+ element: "Tab"
743
+ }, "Item Content"));
744
+ }
745
+ );
746
+ TabContent.defaultProps = {
747
+ rows: 2,
748
+ columns: 12,
749
+ gap: 4,
750
+ rowSize: 48,
751
+ css: {
752
+ "@desktop": {
753
+ width: "100%",
754
+ maxWidth: "var(--grid-size)",
755
+ display: "var(--content-active, none)",
756
+ gridTemplateRows: "repeat(var(--rows), var(--row-size))",
757
+ gridTemplateColumns: "repeat(var(--columns), minmax(0, var(--col-size)))",
758
+ gap: "var(--gap)",
759
+ borderRadius: 4
760
+ }
761
+ }
762
+ };
763
+ var TabContent_default = TabContent;
764
+
765
+ // src/elements/index.ts
766
+ var elements = {
767
+ Countdown: {
768
+ Component: countdown_default,
769
+ type: "countdown"
770
+ },
771
+ Button: {
772
+ Component: button_default,
773
+ type: "button"
774
+ },
775
+ Container: {
776
+ Component: container_default,
777
+ type: "container"
778
+ },
779
+ Image: {
780
+ Component: image_default,
781
+ type: "image"
782
+ },
783
+ Instagram: {
784
+ Component: instagram_default,
785
+ type: "instagram"
786
+ },
787
+ Layout: {
788
+ Component: layout_default,
789
+ type: "layout"
790
+ },
791
+ Map: {
792
+ Component: map_default,
793
+ type: "map"
794
+ },
795
+ Text: {
796
+ Component: text_default,
797
+ type: "text"
798
+ },
799
+ Video: {
800
+ Component: video_default,
801
+ type: "video"
802
+ },
803
+ Accordion: {
804
+ Component: accordion_default,
805
+ type: "accordion"
806
+ },
807
+ AccordionWrapper: {
808
+ Component: AccordionWrapper_default,
809
+ type: "accordion.wrapper"
810
+ },
811
+ AccordionContent: {
812
+ Component: AccordionContent_default,
813
+ type: "accordion.content"
814
+ },
815
+ Tab: {
816
+ Component: tab_default,
817
+ type: "tab"
818
+ },
819
+ TabContent: {
820
+ Component: TabContent_default,
821
+ type: "tab.content"
822
+ }
823
+ };
824
+ var elements_default = elements;
825
+
826
+ // src/context.ts
827
+ var createRootContext = (configs) => {
828
+ let rootContext = new Weaverse(configs);
829
+ Object.keys(elements_default).forEach((key) => {
830
+ rootContext.registerElement(elements_default[key]);
831
+ });
832
+ return rootContext;
833
+ };
834
+ var WeaverseContext = createContext3({});
835
+ var WeaverseContextProvider = WeaverseContext.Provider;
836
+ var WeaverseContextConsumer = WeaverseContext.Consumer;
837
+
838
+ // src/renderer.tsx
839
+ import { isBrowser } from "@weaverse/core";
840
+ import React18, { useContext as useContext7, useEffect as useEffect4, useRef, useState as useState5 } from "react";
841
+
842
+ // src/utils/index.ts
843
+ var shortCssObject = (css) => {
844
+ return {
845
+ "@desktop": css["@desktop"],
846
+ "@mobile": css["@mobile"]
847
+ };
848
+ };
849
+ function generateItemClass(instance, stitchesInstance) {
850
+ var _a, _b, _c, _d;
851
+ let { css, className: cls = "" } = instance.data;
852
+ let defaultCss = ((_c = (_b = (_a = instance.Element) == null ? void 0 : _a.Component) == null ? void 0 : _b.defaultProps) == null ? void 0 : _c.css) || {};
853
+ let className = "";
854
+ if (css || defaultCss) {
855
+ let formattedCss = shortCssObject(css || defaultCss);
856
+ let { className: newClass = "" } = stitchesInstance.css(formattedCss)();
857
+ let { stitchesClass } = instance;
858
+ let otherClass = (((_d = instance.ref.current) == null ? void 0 : _d.className) || "").replace(stitchesClass, "").replace(cls, "").trim();
859
+ className = `${cls} ${newClass} ${otherClass}`.trim();
860
+ instance.stitchesClass = newClass;
861
+ }
862
+ return className;
863
+ }
864
+
865
+ // src/renderer.tsx
866
+ var WeaverseRoot = ({ context }) => {
867
+ var _a, _b;
868
+ let [, setData] = useState5(context.projectData);
869
+ let rootRef = useRef();
870
+ let update = () => setData({});
871
+ useEffect4(() => {
872
+ context.subscribe(update);
873
+ context.contentRootElement = rootRef.current;
874
+ return () => {
875
+ context.unsubscribe(update);
876
+ };
877
+ }, []);
878
+ let eventHandlers = ((_a = context == null ? void 0 : context.studioBridge) == null ? void 0 : _a.eventHandlers) || {};
879
+ let themeClass = context.stitchesInstance.theme.className;
880
+ return ((_b = context.projectData) == null ? void 0 : _b.rootId) ? /* @__PURE__ */ React18.createElement("div", {
881
+ className: `weaverse-content-root ${themeClass}`,
882
+ ...eventHandlers,
883
+ ref: rootRef
884
+ }, /* @__PURE__ */ React18.createElement(WeaverseContextProvider, {
885
+ value: context
886
+ }, /* @__PURE__ */ React18.createElement(ItemInstance, {
887
+ id: context.projectData.rootId
888
+ }))) : null;
889
+ };
890
+ var ItemComponent = ({ instance }) => {
891
+ let { stitchesInstance, elementInstances } = useContext7(WeaverseContext);
892
+ let [data, setData] = useState5(instance.data);
893
+ let { id, type, childIds = [], css, className, ...rest } = data;
894
+ useEffect4(() => {
895
+ var _a;
896
+ let update = (data2) => setData({ ...data2 });
897
+ instance.subscribe(update);
898
+ if (isBrowser && !instance.ref.current) {
899
+ Object.assign(instance.ref, {
900
+ current: document.querySelector(`[data-wv-id="${id}"]`)
901
+ });
902
+ }
903
+ (_a = instance.ref.current) == null ? void 0 : _a.removeAttribute("css");
904
+ return () => {
905
+ instance.unsubscribe(update);
906
+ };
907
+ }, []);
908
+ let Element = elementInstances.get(type);
909
+ if (Element == null ? void 0 : Element.Component) {
910
+ let Component = Element.Component;
911
+ if (Component.$$typeof === Symbol.for("react.forward_ref")) {
912
+ rest.ref = instance.ref;
913
+ }
914
+ return /* @__PURE__ */ React18.createElement(Component, {
915
+ key: id,
916
+ "data-wv-type": type,
917
+ "data-wv-id": id,
918
+ className: generateItemClass(instance, stitchesInstance),
919
+ ...rest
920
+ }, childIds.map((id2) => /* @__PURE__ */ React18.createElement(ItemInstance, {
921
+ key: id2,
922
+ id: id2
923
+ })));
924
+ }
925
+ return null;
926
+ };
927
+ var ItemInstance = ({ id }) => {
928
+ let context = useContext7(WeaverseContext);
929
+ let { itemInstances } = context;
930
+ let instance = itemInstances.get(id);
931
+ if (!instance) {
932
+ return /* @__PURE__ */ React18.createElement("div", {
933
+ style: { display: "none" }
934
+ }, "Item instance ", id, " not found");
935
+ }
936
+ return /* @__PURE__ */ React18.createElement(ItemComponent, {
937
+ instance
938
+ });
939
+ };
940
+
941
+ // src/index.ts
942
+ export * from "@weaverse/core";
943
+ export {
944
+ WeaverseContext,
945
+ WeaverseContextConsumer,
946
+ WeaverseContextProvider,
947
+ WeaverseRoot,
948
+ createRootContext
949
+ };