@squeletteapp/widget-react 0.1.1 → 1.0.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/index.esm.js CHANGED
@@ -1,359 +1,158 @@
1
- // src/index.ts
2
- import {
3
- createChangelogWidget as createChangelogWidget2,
4
- createFeedbackWidget as createFeedbackWidget2,
5
- createRoadmapWidget as createRoadmapWidget2,
6
- createWidget as createWidget2
7
- } from "@squeletteapp/widget";
8
-
9
- // ../../node_modules/@radix-ui/react-slot/dist/index.mjs
10
- import * as React2 from "react";
11
-
12
- // ../../node_modules/@radix-ui/react-compose-refs/dist/index.mjs
1
+ // src/context.tsx
13
2
  import * as React from "react";
14
- function setRef(ref, value) {
15
- if (typeof ref === "function") {
16
- return ref(value);
17
- } else if (ref !== null && ref !== void 0) {
18
- ref.current = value;
19
- }
20
- }
21
- function composeRefs(...refs) {
22
- return (node) => {
23
- let hasCleanup = false;
24
- const cleanups = refs.map((ref) => {
25
- const cleanup = setRef(ref, node);
26
- if (!hasCleanup && typeof cleanup == "function") {
27
- hasCleanup = true;
28
- }
29
- return cleanup;
30
- });
31
- if (hasCleanup) {
32
- return () => {
33
- for (let i = 0; i < cleanups.length; i++) {
34
- const cleanup = cleanups[i];
35
- if (typeof cleanup == "function") {
36
- cleanup();
37
- } else {
38
- setRef(refs[i], null);
39
- }
40
- }
41
- };
42
- }
43
- };
44
- }
45
-
46
- // ../../node_modules/@radix-ui/react-slot/dist/index.mjs
47
- import { Fragment as Fragment2, jsx } from "react/jsx-runtime";
48
- // @__NO_SIDE_EFFECTS__
49
- function createSlot(ownerName) {
50
- const SlotClone = /* @__PURE__ */ createSlotClone(ownerName);
51
- const Slot2 = React2.forwardRef((props, forwardedRef) => {
52
- const { children, ...slotProps } = props;
53
- const childrenArray = React2.Children.toArray(children);
54
- const slottable = childrenArray.find(isSlottable);
55
- if (slottable) {
56
- const newElement = slottable.props.children;
57
- const newChildren = childrenArray.map((child) => {
58
- if (child === slottable) {
59
- if (React2.Children.count(newElement) > 1) return React2.Children.only(null);
60
- return React2.isValidElement(newElement) ? newElement.props.children : null;
61
- } else {
62
- return child;
63
- }
3
+ import { jsx } from "react/jsx-runtime";
4
+ var ChangelogContext = React.createContext(null);
5
+ function ChangelogProvider({
6
+ children,
7
+ slug,
8
+ theme = "light",
9
+ base
10
+ }) {
11
+ const [context, setContext] = React.useState(null);
12
+ React.useEffect(() => {
13
+ import("@squeletteapp/widget").then((mod) => {
14
+ const widgetModule = mod;
15
+ setContext({
16
+ store: widgetModule.createChangelogStore(),
17
+ module: widgetModule
64
18
  });
65
- return /* @__PURE__ */ jsx(SlotClone, { ...slotProps, ref: forwardedRef, children: React2.isValidElement(newElement) ? React2.cloneElement(newElement, void 0, newChildren) : null });
66
- }
67
- return /* @__PURE__ */ jsx(SlotClone, { ...slotProps, ref: forwardedRef, children });
68
- });
69
- Slot2.displayName = `${ownerName}.Slot`;
70
- return Slot2;
71
- }
72
- var Slot = /* @__PURE__ */ createSlot("Slot");
73
- // @__NO_SIDE_EFFECTS__
74
- function createSlotClone(ownerName) {
75
- const SlotClone = React2.forwardRef((props, forwardedRef) => {
76
- const { children, ...slotProps } = props;
77
- if (React2.isValidElement(children)) {
78
- const childrenRef = getElementRef(children);
79
- const props2 = mergeProps(slotProps, children.props);
80
- if (children.type !== React2.Fragment) {
81
- props2.ref = forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef;
82
- }
83
- return React2.cloneElement(children, props2);
84
- }
85
- return React2.Children.count(children) > 1 ? React2.Children.only(null) : null;
86
- });
87
- SlotClone.displayName = `${ownerName}.SlotClone`;
88
- return SlotClone;
89
- }
90
- var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
91
- function isSlottable(child) {
92
- return React2.isValidElement(child) && typeof child.type === "function" && "__radixId" in child.type && child.type.__radixId === SLOTTABLE_IDENTIFIER;
93
- }
94
- function mergeProps(slotProps, childProps) {
95
- const overrideProps = { ...childProps };
96
- for (const propName in childProps) {
97
- const slotPropValue = slotProps[propName];
98
- const childPropValue = childProps[propName];
99
- const isHandler = /^on[A-Z]/.test(propName);
100
- if (isHandler) {
101
- if (slotPropValue && childPropValue) {
102
- overrideProps[propName] = (...args) => {
103
- const result = childPropValue(...args);
104
- slotPropValue(...args);
105
- return result;
106
- };
107
- } else if (slotPropValue) {
108
- overrideProps[propName] = slotPropValue;
109
- }
110
- } else if (propName === "style") {
111
- overrideProps[propName] = { ...slotPropValue, ...childPropValue };
112
- } else if (propName === "className") {
113
- overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(" ");
114
- }
19
+ });
20
+ }, []);
21
+ React.useEffect(() => {
22
+ context?.store.setTheme(theme);
23
+ }, [context, theme]);
24
+ if (!context) {
25
+ return null;
115
26
  }
116
- return { ...slotProps, ...overrideProps };
27
+ return /* @__PURE__ */ jsx(
28
+ ChangelogContext.Provider,
29
+ {
30
+ value: { store: context.store, module: context.module, theme, base, slug },
31
+ children
32
+ }
33
+ );
117
34
  }
118
- function getElementRef(element) {
119
- let getter = Object.getOwnPropertyDescriptor(element.props, "ref")?.get;
120
- let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
121
- if (mayWarn) {
122
- return element.ref;
35
+ function useChangelogContext() {
36
+ const context = React.useContext(ChangelogContext);
37
+ if (!context) {
38
+ throw new Error("useChangelogContext must be used within a ChangelogProvider");
123
39
  }
124
- getter = Object.getOwnPropertyDescriptor(element, "ref")?.get;
125
- mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
126
- if (mayWarn) {
127
- return element.props.ref;
128
- }
129
- return element.props.ref || element.ref;
40
+ return context;
130
41
  }
131
42
 
132
- // src/components.tsx
133
- import * as React3 from "react";
134
-
135
- // src/hooks.ts
136
- import {
137
- createChangelogWidget,
138
- createFeedbackWidget,
139
- createRoadmapWidget,
140
- createWidget
141
- } from "@squeletteapp/widget";
142
- import { useCallback as useCallback2, useEffect, useRef } from "react";
143
- function useFeedbackWidget(workspaceSlug, boardSlug, options) {
144
- const widgetRef = useRef(null);
145
- const onOpenChangeRef = useRef(options.onOpenChange);
146
- onOpenChangeRef.current = options.onOpenChange;
147
- const initWidget = useCallback2(() => {
148
- if (widgetRef.current) {
149
- widgetRef.current.destroy();
150
- }
151
- const element = document.querySelector(options.buttonSelector);
152
- if (!element) {
153
- return null;
154
- }
155
- widgetRef.current = createFeedbackWidget(workspaceSlug, boardSlug, {
156
- ...options,
157
- onOpenChange: onOpenChangeRef.current ? (isOpen) => onOpenChangeRef.current?.(isOpen) : void 0
158
- });
159
- return widgetRef.current;
160
- }, [
161
- workspaceSlug,
162
- boardSlug,
163
- options.buttonSelector,
164
- options.position,
165
- options.theme,
166
- options.onLoad
167
- ]);
168
- useEffect(() => {
169
- const frame = requestAnimationFrame(() => {
170
- const widget = initWidget();
171
- widgetRef.current = widget;
43
+ // src/components/changelog-entry-modal.tsx
44
+ import * as React2 from "react";
45
+ function ChangelogEntryModal({
46
+ ticketId,
47
+ onOpenChange
48
+ }) {
49
+ const { store, module, theme, base, slug } = useChangelogContext();
50
+ const widgetRef = React2.useRef(null);
51
+ React2.useEffect(() => {
52
+ const widget = module.createChangelogEntryWidget(ticketId, {
53
+ base,
54
+ contentTheme: theme,
55
+ slug
172
56
  });
173
- return () => {
174
- cancelAnimationFrame(frame);
175
- if (widgetRef.current) {
176
- widgetRef.current.destroy();
177
- }
178
- };
179
- }, [initWidget]);
180
- return widgetRef.current;
181
- }
182
- function useRoadmapWidget(workspaceSlug, boardSlug, options) {
183
- const widgetRef = useRef(null);
184
- const initWidget = useCallback2(() => {
185
- if (widgetRef.current) {
186
- widgetRef.current.destroy();
187
- }
188
- const element = document.querySelector(options.buttonSelector);
189
- if (!element) {
190
- return null;
57
+ if (onOpenChange) {
58
+ widget.onOpenChange(onOpenChange);
191
59
  }
192
- widgetRef.current = createRoadmapWidget(workspaceSlug, boardSlug, options);
193
- return widgetRef.current;
194
- }, [workspaceSlug, boardSlug, options]);
195
- useEffect(() => {
196
- const frame = requestAnimationFrame(() => {
197
- const widget = initWidget();
198
- widgetRef.current = widget;
199
- });
60
+ widgetRef.current = widget;
61
+ store.mount(ticketId, widget);
200
62
  return () => {
201
- cancelAnimationFrame(frame);
202
- if (widgetRef.current) {
203
- widgetRef.current.destroy();
204
- }
63
+ store.unmount(ticketId);
64
+ widgetRef.current = null;
205
65
  };
206
- }, [initWidget]);
207
- return widgetRef.current;
66
+ }, [ticketId, slug, store, module, base, onOpenChange, theme]);
67
+ React2.useEffect(() => {
68
+ widgetRef.current?.setTheme(theme);
69
+ }, [theme]);
70
+ return null;
208
71
  }
209
- function useChangelogWidget(workspaceSlug, options) {
210
- const widgetRef = useRef(null);
211
- const onOpenChangeRef = useRef(options.onOpenChange);
212
- onOpenChangeRef.current = options.onOpenChange;
213
- const initWidget = useCallback2(() => {
214
- if (widgetRef.current) {
215
- widgetRef.current.destroy();
216
- }
217
- const element = document.querySelector(options.buttonSelector);
218
- if (!element) {
219
- return null;
220
- }
221
- widgetRef.current = createChangelogWidget(workspaceSlug, {
222
- ...options,
223
- onOpenChange: onOpenChangeRef.current ? (isOpen) => onOpenChangeRef.current?.(isOpen) : void 0
224
- });
225
- return widgetRef.current;
226
- }, [
227
- workspaceSlug,
228
- options.buttonSelector,
229
- options.position,
230
- options.theme,
231
- options.onLoad
232
- ]);
233
- useEffect(() => {
234
- const frame = requestAnimationFrame(() => {
235
- const widget = initWidget();
236
- widgetRef.current = widget;
237
- });
238
- return () => {
239
- cancelAnimationFrame(frame);
240
- if (widgetRef.current) {
241
- widgetRef.current.destroy();
72
+
73
+ // src/components/changelog-entries-list-dropdown.tsx
74
+ import * as React3 from "react";
75
+ function ChangelogEntriesListDropdown({
76
+ children,
77
+ position
78
+ }) {
79
+ const { store, module, theme, base, slug } = useChangelogContext();
80
+ const widgetRef = React3.useRef(null);
81
+ const anchorId = React3.useId();
82
+ const cleanAnchorId = `sq-dropdown-${anchorId.replace(/:/g, "")}`;
83
+ const initialThemeRef = React3.useRef(theme);
84
+ React3.useEffect(() => {
85
+ const widget = module.createChangelogEntriesListDropdownWidget(
86
+ `#${cleanAnchorId}`,
87
+ store,
88
+ {
89
+ base,
90
+ contentTheme: initialThemeRef.current,
91
+ slug,
92
+ position
242
93
  }
94
+ );
95
+ widget.preload();
96
+ widgetRef.current = widget;
97
+ return () => {
98
+ widget.destroy();
99
+ widgetRef.current = null;
243
100
  };
244
- }, [initWidget]);
245
- return widgetRef.current;
246
- }
247
- function useWidget(options) {
248
- const widgetRef = useRef(null);
249
- const initWidget = useCallback2(() => {
250
- if (widgetRef.current) {
251
- widgetRef.current.destroy();
252
- }
253
- const element = document.querySelector(options.buttonSelector);
254
- if (!element) {
255
- return null;
101
+ }, [slug, store, module, base, cleanAnchorId, position]);
102
+ React3.useEffect(() => {
103
+ widgetRef.current?.setTheme(theme);
104
+ }, [theme]);
105
+ const handleClick = React3.useCallback(() => {
106
+ widgetRef.current?.open();
107
+ }, []);
108
+ return React3.cloneElement(children, {
109
+ id: cleanAnchorId,
110
+ onClick: (e) => {
111
+ const originalOnClick = children.props.onClick;
112
+ if (originalOnClick) {
113
+ originalOnClick(e);
114
+ }
115
+ handleClick();
256
116
  }
257
- widgetRef.current = createWidget(options);
258
- return widgetRef.current;
259
- }, [options]);
260
- useEffect(() => {
261
- const frame = requestAnimationFrame(() => {
262
- const widget = initWidget();
263
- widgetRef.current = widget;
117
+ });
118
+ }
119
+
120
+ // src/components/changelog-banner.tsx
121
+ import * as React4 from "react";
122
+ function ChangelogBanner({ debug = false }) {
123
+ const { store, module, theme, base, slug } = useChangelogContext();
124
+ const widgetRef = React4.useRef(null);
125
+ const initialThemeRef = React4.useRef(theme);
126
+ React4.useEffect(() => {
127
+ let mounted = true;
128
+ module.createChangelogBannerWidget(store, {
129
+ base,
130
+ contentTheme: initialThemeRef.current,
131
+ slug,
132
+ debug
133
+ }).then((widget) => {
134
+ if (mounted && widget) {
135
+ widgetRef.current = widget;
136
+ }
264
137
  });
265
138
  return () => {
266
- cancelAnimationFrame(frame);
139
+ mounted = false;
267
140
  if (widgetRef.current) {
268
141
  widgetRef.current.destroy();
142
+ widgetRef.current = null;
269
143
  }
270
144
  };
271
- }, [initWidget]);
272
- return widgetRef.current;
273
- }
274
-
275
- // src/components.tsx
276
- import { jsx as jsx2 } from "react/jsx-runtime";
277
- function FeedbackWidget({
278
- workspaceSlug,
279
- boardSlug,
280
- children,
281
- className,
282
- asChild = false,
283
- onOpenChange,
284
- ...options
285
- }) {
286
- const buttonId = React3.useId();
287
- useFeedbackWidget(workspaceSlug, boardSlug, {
288
- ...options,
289
- buttonSelector: `#${buttonId}`,
290
- onOpenChange
291
- });
292
- if (asChild) {
293
- return React3.createElement(
294
- Slot,
295
- { className, id: buttonId },
296
- children
297
- );
298
- }
299
- return /* @__PURE__ */ jsx2("button", { className, id: buttonId, type: "button", children });
300
- }
301
- function RoadmapWidget({
302
- workspaceSlug,
303
- boardSlug,
304
- children,
305
- className,
306
- asChild = false,
307
- ...options
308
- }) {
309
- const buttonId = React3.useId();
310
- useRoadmapWidget(workspaceSlug, boardSlug, {
311
- ...options,
312
- buttonSelector: `#${buttonId}`
313
- });
314
- if (asChild) {
315
- return React3.createElement(
316
- Slot,
317
- { className, id: buttonId },
318
- children
319
- );
320
- }
321
- return /* @__PURE__ */ jsx2("button", { className, id: buttonId, type: "button", children });
322
- }
323
- function ChangelogWidget({
324
- workspaceSlug,
325
- children,
326
- className,
327
- asChild = false,
328
- onOpenChange,
329
- ...options
330
- }) {
331
- const buttonId = React3.useId();
332
- useChangelogWidget(workspaceSlug, {
333
- ...options,
334
- buttonSelector: `#${buttonId}`,
335
- onOpenChange
336
- });
337
- if (asChild) {
338
- return React3.createElement(
339
- Slot,
340
- { className, id: buttonId },
341
- children
342
- );
343
- }
344
- return /* @__PURE__ */ jsx2("button", { className, id: buttonId, type: "button", children });
145
+ }, [slug, store, module, base, debug]);
146
+ React4.useEffect(() => {
147
+ widgetRef.current?.setTheme(theme);
148
+ }, [theme]);
149
+ return null;
345
150
  }
346
151
  export {
347
- ChangelogWidget,
348
- FeedbackWidget,
349
- RoadmapWidget,
350
- createChangelogWidget2 as createChangelogWidget,
351
- createFeedbackWidget2 as createFeedbackWidget,
352
- createRoadmapWidget2 as createRoadmapWidget,
353
- createWidget2 as createWidget,
354
- useChangelogWidget,
355
- useFeedbackWidget,
356
- useRoadmapWidget,
357
- useWidget
152
+ ChangelogBanner,
153
+ ChangelogEntriesListDropdown,
154
+ ChangelogEntryModal,
155
+ ChangelogProvider,
156
+ useChangelogContext
358
157
  };
359
158
  //# sourceMappingURL=index.esm.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.ts", "../../../node_modules/@radix-ui/react-slot/src/slot.tsx", "../../../node_modules/@radix-ui/react-compose-refs/src/compose-refs.tsx", "../src/components.tsx", "../src/hooks.ts"],
4
- "sourcesContent": ["export {\n createChangelogWidget,\n createFeedbackWidget,\n createRoadmapWidget,\n createWidget,\n} from '@squeletteapp/widget';\n\nexport {\n ChangelogWidget,\n type ChangelogWidgetProps,\n FeedbackWidget,\n type FeedbackWidgetProps,\n RoadmapWidget,\n type RoadmapWidgetProps,\n} from './components';\nexport {\n useChangelogWidget,\n useFeedbackWidget,\n useRoadmapWidget,\n useWidget,\n type WidgetInstance,\n type WidgetOptions,\n} from './hooks';\n", "import * as React from 'react';\nimport { composeRefs } from '@radix-ui/react-compose-refs';\n\n/* -------------------------------------------------------------------------------------------------\n * Slot\n * -----------------------------------------------------------------------------------------------*/\n\ninterface SlotProps extends React.HTMLAttributes<HTMLElement> {\n children?: React.ReactNode;\n}\n\n/* @__NO_SIDE_EFFECTS__ */ export function createSlot(ownerName: string) {\n const SlotClone = createSlotClone(ownerName);\n const Slot = React.forwardRef<HTMLElement, SlotProps>((props, forwardedRef) => {\n const { children, ...slotProps } = props;\n const childrenArray = React.Children.toArray(children);\n const slottable = childrenArray.find(isSlottable);\n\n if (slottable) {\n // the new element to render is the one passed as a child of `Slottable`\n const newElement = slottable.props.children;\n\n const newChildren = childrenArray.map((child) => {\n if (child === slottable) {\n // because the new element will be the one rendered, we are only interested\n // in grabbing its children (`newElement.props.children`)\n if (React.Children.count(newElement) > 1) return React.Children.only(null);\n return React.isValidElement(newElement)\n ? (newElement.props as { children: React.ReactNode }).children\n : null;\n } else {\n return child;\n }\n });\n\n return (\n <SlotClone {...slotProps} ref={forwardedRef}>\n {React.isValidElement(newElement)\n ? React.cloneElement(newElement, undefined, newChildren)\n : null}\n </SlotClone>\n );\n }\n\n return (\n <SlotClone {...slotProps} ref={forwardedRef}>\n {children}\n </SlotClone>\n );\n });\n\n Slot.displayName = `${ownerName}.Slot`;\n return Slot;\n}\n\nconst Slot = createSlot('Slot');\n\n/* -------------------------------------------------------------------------------------------------\n * SlotClone\n * -----------------------------------------------------------------------------------------------*/\n\ninterface SlotCloneProps {\n children: React.ReactNode;\n}\n\n/* @__NO_SIDE_EFFECTS__ */ function createSlotClone(ownerName: string) {\n const SlotClone = React.forwardRef<any, SlotCloneProps>((props, forwardedRef) => {\n const { children, ...slotProps } = props;\n\n if (React.isValidElement(children)) {\n const childrenRef = getElementRef(children);\n const props = mergeProps(slotProps, children.props as AnyProps);\n // do not pass ref to React.Fragment for React 19 compatibility\n if (children.type !== React.Fragment) {\n props.ref = forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef;\n }\n return React.cloneElement(children, props);\n }\n\n return React.Children.count(children) > 1 ? React.Children.only(null) : null;\n });\n\n SlotClone.displayName = `${ownerName}.SlotClone`;\n return SlotClone;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Slottable\n * -----------------------------------------------------------------------------------------------*/\n\nconst SLOTTABLE_IDENTIFIER = Symbol('radix.slottable');\n\ninterface SlottableProps {\n children: React.ReactNode;\n}\n\ninterface SlottableComponent extends React.FC<SlottableProps> {\n __radixId: symbol;\n}\n\n/* @__NO_SIDE_EFFECTS__ */ export function createSlottable(ownerName: string) {\n const Slottable: SlottableComponent = ({ children }) => {\n return <>{children}</>;\n };\n Slottable.displayName = `${ownerName}.Slottable`;\n Slottable.__radixId = SLOTTABLE_IDENTIFIER;\n return Slottable;\n}\n\nconst Slottable = createSlottable('Slottable');\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype AnyProps = Record<string, any>;\n\nfunction isSlottable(\n child: React.ReactNode\n): child is React.ReactElement<SlottableProps, typeof Slottable> {\n return (\n React.isValidElement(child) &&\n typeof child.type === 'function' &&\n '__radixId' in child.type &&\n child.type.__radixId === SLOTTABLE_IDENTIFIER\n );\n}\n\nfunction mergeProps(slotProps: AnyProps, childProps: AnyProps) {\n // all child props should override\n const overrideProps = { ...childProps };\n\n for (const propName in childProps) {\n const slotPropValue = slotProps[propName];\n const childPropValue = childProps[propName];\n\n const isHandler = /^on[A-Z]/.test(propName);\n if (isHandler) {\n // if the handler exists on both, we compose them\n if (slotPropValue && childPropValue) {\n overrideProps[propName] = (...args: unknown[]) => {\n const result = childPropValue(...args);\n slotPropValue(...args);\n return result;\n };\n }\n // but if it exists only on the slot, we use only this one\n else if (slotPropValue) {\n overrideProps[propName] = slotPropValue;\n }\n }\n // if it's `style`, we merge them\n else if (propName === 'style') {\n overrideProps[propName] = { ...slotPropValue, ...childPropValue };\n } else if (propName === 'className') {\n overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(' ');\n }\n }\n\n return { ...slotProps, ...overrideProps };\n}\n\n// Before React 19 accessing `element.props.ref` will throw a warning and suggest using `element.ref`\n// After React 19 accessing `element.ref` does the opposite.\n// https://github.com/facebook/react/pull/28348\n//\n// Access the ref using the method that doesn't yield a warning.\nfunction getElementRef(element: React.ReactElement) {\n // React <=18 in DEV\n let getter = Object.getOwnPropertyDescriptor(element.props, 'ref')?.get;\n let mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;\n if (mayWarn) {\n return (element as any).ref;\n }\n\n // React 19 in DEV\n getter = Object.getOwnPropertyDescriptor(element, 'ref')?.get;\n mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;\n if (mayWarn) {\n return (element.props as { ref?: React.Ref<unknown> }).ref;\n }\n\n // Not DEV\n return (element.props as { ref?: React.Ref<unknown> }).ref || (element as any).ref;\n}\n\nexport {\n Slot,\n Slottable,\n //\n Slot as Root,\n};\nexport type { SlotProps };\n", "import * as React from 'react';\n\ntype PossibleRef<T> = React.Ref<T> | undefined;\n\n/**\n * Set a given ref to a given value\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nfunction setRef<T>(ref: PossibleRef<T>, value: T) {\n if (typeof ref === 'function') {\n return ref(value);\n } else if (ref !== null && ref !== undefined) {\n ref.current = value;\n }\n}\n\n/**\n * A utility to compose multiple refs together\n * Accepts callback refs and RefObject(s)\n */\nfunction composeRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n return (node) => {\n let hasCleanup = false;\n const cleanups = refs.map((ref) => {\n const cleanup = setRef(ref, node);\n if (!hasCleanup && typeof cleanup == 'function') {\n hasCleanup = true;\n }\n return cleanup;\n });\n\n // React <19 will log an error to the console if a callback ref returns a\n // value. We don't use ref cleanups internally so this will only happen if a\n // user's ref callback returns a value, which we only expect if they are\n // using the cleanup functionality added in React 19.\n if (hasCleanup) {\n return () => {\n for (let i = 0; i < cleanups.length; i++) {\n const cleanup = cleanups[i];\n if (typeof cleanup == 'function') {\n cleanup();\n } else {\n setRef(refs[i], null);\n }\n }\n };\n }\n };\n}\n\n/**\n * A custom hook that composes multiple refs\n * Accepts callback refs and RefObject(s)\n */\nfunction useComposedRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return React.useCallback(composeRefs(...refs), refs);\n}\n\nexport { composeRefs, useComposedRefs };\n", "import { Slot } from '@radix-ui/react-slot';\nimport * as React from 'react';\nimport {\n useChangelogWidget,\n useFeedbackWidget,\n useRoadmapWidget,\n type WidgetOptions,\n} from './hooks';\n\nexport interface FeedbackWidgetProps\n extends Omit<WidgetOptions, 'buttonSelector'> {\n workspaceSlug: string;\n boardSlug?: string;\n children: React.ReactNode;\n className?: string;\n asChild?: boolean;\n onOpenChange?: (isOpen: boolean) => void;\n}\n\nexport interface RoadmapWidgetProps\n extends Omit<WidgetOptions, 'buttonSelector'> {\n workspaceSlug: string;\n boardSlug: string;\n children: React.ReactNode;\n className?: string;\n asChild?: boolean;\n}\n\nexport interface ChangelogWidgetProps\n extends Omit<WidgetOptions, 'buttonSelector'> {\n workspaceSlug: string;\n children: React.ReactNode;\n className?: string;\n asChild?: boolean;\n onOpenChange?: (isOpen: boolean) => void;\n}\n\nexport function FeedbackWidget({\n workspaceSlug,\n boardSlug,\n children,\n className,\n asChild = false,\n onOpenChange,\n ...options\n}: FeedbackWidgetProps) {\n const buttonId = React.useId();\n\n useFeedbackWidget(workspaceSlug, boardSlug, {\n ...options,\n buttonSelector: `#${buttonId}`,\n onOpenChange,\n });\n\n if (asChild) {\n return React.createElement(\n Slot as any,\n { className, id: buttonId },\n children\n );\n }\n\n return (\n <button className={className} id={buttonId} type=\"button\">\n {children}\n </button>\n );\n}\n\nexport function RoadmapWidget({\n workspaceSlug,\n boardSlug,\n children,\n className,\n asChild = false,\n ...options\n}: RoadmapWidgetProps) {\n const buttonId = React.useId();\n\n useRoadmapWidget(workspaceSlug, boardSlug, {\n ...options,\n buttonSelector: `#${buttonId}`,\n });\n\n if (asChild) {\n return React.createElement(\n Slot as any,\n { className, id: buttonId },\n children\n );\n }\n\n return (\n <button className={className} id={buttonId} type=\"button\">\n {children}\n </button>\n );\n}\n\nexport function ChangelogWidget({\n workspaceSlug,\n children,\n className,\n asChild = false,\n onOpenChange,\n ...options\n}: ChangelogWidgetProps) {\n const buttonId = React.useId();\n\n useChangelogWidget(workspaceSlug, {\n ...options,\n buttonSelector: `#${buttonId}`,\n onOpenChange,\n });\n\n if (asChild) {\n return React.createElement(\n Slot as any,\n { className, id: buttonId },\n children\n );\n }\n\n return (\n <button className={className} id={buttonId} type=\"button\">\n {children}\n </button>\n );\n}\n", "import {\n createChangelogWidget,\n createFeedbackWidget,\n createRoadmapWidget,\n createWidget,\n} from '@squeletteapp/widget';\nimport { useCallback, useEffect, useRef } from 'react';\n\nexport interface WidgetOptions {\n buttonSelector: string;\n position?: 'top' | 'bottom' | 'left' | 'right';\n theme?: string;\n onLoad?: () => void;\n onOpenChange?: (isOpen: boolean) => void;\n}\n\nexport interface WidgetInstance {\n destroy: () => void;\n}\n\nexport function useFeedbackWidget(\n workspaceSlug: string,\n boardSlug: string | undefined,\n options: WidgetOptions\n): WidgetInstance | null {\n const widgetRef = useRef<WidgetInstance | null>(null);\n const onOpenChangeRef = useRef(options.onOpenChange);\n\n // Always keep the latest onOpenChange callback\n onOpenChangeRef.current = options.onOpenChange;\n\n const initWidget = useCallback(() => {\n if (widgetRef.current) {\n widgetRef.current.destroy();\n }\n\n const element = document.querySelector(options.buttonSelector);\n if (!element) {\n return null;\n }\n\n widgetRef.current = createFeedbackWidget(workspaceSlug, boardSlug, {\n ...options,\n onOpenChange: onOpenChangeRef.current\n ? (isOpen: boolean) => onOpenChangeRef.current?.(isOpen)\n : undefined,\n });\n return widgetRef.current;\n }, [\n workspaceSlug,\n boardSlug,\n options.buttonSelector,\n options.position,\n options.theme,\n options.onLoad,\n ]);\n\n useEffect(() => {\n // Use requestAnimationFrame to ensure DOM is ready\n const frame = requestAnimationFrame(() => {\n const widget = initWidget();\n widgetRef.current = widget;\n });\n\n return () => {\n cancelAnimationFrame(frame);\n if (widgetRef.current) {\n widgetRef.current.destroy();\n }\n };\n }, [initWidget]);\n\n return widgetRef.current;\n}\n\nexport function useRoadmapWidget(\n workspaceSlug: string,\n boardSlug: string,\n options: WidgetOptions\n): WidgetInstance | null {\n const widgetRef = useRef<WidgetInstance | null>(null);\n\n const initWidget = useCallback(() => {\n if (widgetRef.current) {\n widgetRef.current.destroy();\n }\n\n const element = document.querySelector(options.buttonSelector);\n if (!element) {\n return null;\n }\n\n widgetRef.current = createRoadmapWidget(workspaceSlug, boardSlug, options);\n return widgetRef.current;\n }, [workspaceSlug, boardSlug, options]);\n\n useEffect(() => {\n // Use requestAnimationFrame to ensure DOM is ready\n const frame = requestAnimationFrame(() => {\n const widget = initWidget();\n widgetRef.current = widget;\n });\n\n return () => {\n cancelAnimationFrame(frame);\n if (widgetRef.current) {\n widgetRef.current.destroy();\n }\n };\n }, [initWidget]);\n\n return widgetRef.current;\n}\n\nexport function useChangelogWidget(\n workspaceSlug: string,\n options: WidgetOptions\n): WidgetInstance | null {\n const widgetRef = useRef<WidgetInstance | null>(null);\n const onOpenChangeRef = useRef(options.onOpenChange);\n\n // Always keep the latest onOpenChange callback\n onOpenChangeRef.current = options.onOpenChange;\n\n const initWidget = useCallback(() => {\n if (widgetRef.current) {\n widgetRef.current.destroy();\n }\n\n const element = document.querySelector(options.buttonSelector);\n if (!element) {\n return null;\n }\n\n widgetRef.current = createChangelogWidget(workspaceSlug, {\n ...options,\n onOpenChange: onOpenChangeRef.current\n ? (isOpen: boolean) => onOpenChangeRef.current?.(isOpen)\n : undefined,\n });\n return widgetRef.current;\n }, [\n workspaceSlug,\n options.buttonSelector,\n options.position,\n options.theme,\n options.onLoad,\n ]);\n\n useEffect(() => {\n // Use requestAnimationFrame to ensure DOM is ready\n const frame = requestAnimationFrame(() => {\n const widget = initWidget();\n widgetRef.current = widget;\n });\n\n return () => {\n cancelAnimationFrame(frame);\n if (widgetRef.current) {\n widgetRef.current.destroy();\n }\n };\n }, [initWidget]);\n\n return widgetRef.current;\n}\n\nexport function useWidget(options: {\n url: string;\n buttonSelector: string;\n position?: 'top' | 'bottom' | 'left' | 'right';\n onLoad?: () => void;\n onOpenChange?: (isOpen: boolean) => void;\n}): WidgetInstance | null {\n const widgetRef = useRef<WidgetInstance | null>(null);\n\n const initWidget = useCallback(() => {\n if (widgetRef.current) {\n widgetRef.current.destroy();\n }\n\n const element = document.querySelector(options.buttonSelector);\n if (!element) {\n return null;\n }\n\n widgetRef.current = createWidget(options);\n return widgetRef.current;\n }, [options]);\n\n useEffect(() => {\n // Use requestAnimationFrame to ensure DOM is ready\n const frame = requestAnimationFrame(() => {\n const widget = initWidget();\n widgetRef.current = widget;\n });\n\n return () => {\n cancelAnimationFrame(frame);\n if (widgetRef.current) {\n widgetRef.current.destroy();\n }\n };\n }, [initWidget]);\n\n return widgetRef.current;\n}\n"],
5
- "mappings": "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",
6
- "names": ["createChangelogWidget", "createFeedbackWidget", "createRoadmapWidget", "createWidget", "React", "Fragment", "Slot", "props", "React", "useCallback", "jsx"]
3
+ "sources": ["../src/context.tsx", "../src/components/changelog-entry-modal.tsx", "../src/components/changelog-entries-list-dropdown.tsx", "../src/components/changelog-banner.tsx"],
4
+ "sourcesContent": ["'use client';\n\nimport * as React from 'react';\nimport type { ContentTheme } from './types';\n\n// Lazy-loaded types - we don't import the actual module at the top level\ntype WidgetStore = {\n getState: () => Record<string, unknown>;\n mount: (source: string, widget: unknown) => Promise<void>;\n unmount: (source: string) => void;\n open: (source: string) => Promise<void>;\n setTheme: (theme: ContentTheme) => void;\n};\n\ntype WidgetModule = {\n createChangelogStore: () => WidgetStore;\n createChangelogEntryWidget: (\n ticketId: string,\n options: { base?: string; contentTheme?: ContentTheme; slug?: string }\n ) => unknown;\n createChangelogBannerWidget: (\n store: WidgetStore,\n options: { base?: string; contentTheme?: ContentTheme; slug: string; debug?: boolean }\n ) => Promise<unknown>;\n createChangelogEntriesListDropdownWidget: (\n anchor: string,\n store: WidgetStore,\n options: { base?: string; contentTheme?: ContentTheme; slug?: string; position?: 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw' | 'center' }\n ) => unknown;\n};\n\ntype ChangelogContextValue = {\n store: WidgetStore;\n module: WidgetModule;\n theme: ContentTheme;\n base?: string;\n slug: string;\n};\n\nconst ChangelogContext = React.createContext<ChangelogContextValue | null>(null);\n\nexport interface ChangelogProviderProps {\n children: React.ReactNode;\n slug: string;\n theme?: ContentTheme;\n base?: string;\n}\n\n/**\n * ChangelogProvider - Provides changelog store and configuration to child components\n *\n * This provider handles:\n * - Creating and managing the widget store (client-side only)\n * - Syncing theme changes to all widgets\n * - Providing base URL and slug to all child components\n */\nexport function ChangelogProvider({\n children,\n slug,\n theme = 'light',\n base,\n}: ChangelogProviderProps) {\n const [context, setContext] = React.useState<{\n store: WidgetStore;\n module: WidgetModule;\n } | null>(null);\n\n // Initialize store on client side only\n React.useEffect(() => {\n import('@squeletteapp/widget').then((mod) => {\n const widgetModule = mod as unknown as WidgetModule;\n setContext({\n store: widgetModule.createChangelogStore(),\n module: widgetModule,\n });\n });\n }, []);\n\n // Update theme when it changes\n React.useEffect(() => {\n context?.store.setTheme(theme);\n }, [context, theme]);\n\n // Don't render children until store is ready (client-side only)\n if (!context) {\n return null;\n }\n\n return (\n <ChangelogContext.Provider\n value={{ store: context.store, module: context.module, theme, base, slug }}\n >\n {children}\n </ChangelogContext.Provider>\n );\n}\n\nexport function useChangelogContext(): ChangelogContextValue {\n const context = React.useContext(ChangelogContext);\n if (!context) {\n throw new Error('useChangelogContext must be used within a ChangelogProvider');\n }\n return context;\n}\n", "'use client';\n\nimport * as React from 'react';\nimport { useChangelogContext } from '../context';\n\nexport interface ChangelogEntryModalProps {\n ticketId: string;\n onOpenChange?: (isOpen: boolean) => void;\n}\n\n/**\n * ChangelogEntryModal - Renders a modal for a single changelog entry\n *\n * This component manages its own widget lifecycle and automatically\n * cleans up on unmount. Must be used within a ChangelogProvider.\n */\nexport function ChangelogEntryModal({\n ticketId,\n onOpenChange,\n}: ChangelogEntryModalProps) {\n const { store, module, theme, base, slug } = useChangelogContext();\n const widgetRef = React.useRef<{ setTheme: (t: string) => void } | null>(null);\n\n React.useEffect(() => {\n const widget = module.createChangelogEntryWidget(ticketId, {\n base,\n contentTheme: theme,\n slug,\n }) as { onOpenChange: (cb: (isOpen: boolean) => void) => void; setTheme: (t: string) => void };\n\n if (onOpenChange) {\n widget.onOpenChange(onOpenChange);\n }\n\n widgetRef.current = widget;\n store.mount(ticketId, widget);\n\n return () => {\n store.unmount(ticketId);\n widgetRef.current = null;\n };\n }, [ticketId, slug, store, module, base, onOpenChange, theme]);\n\n // Update theme when it changes\n React.useEffect(() => {\n widgetRef.current?.setTheme(theme);\n }, [theme]);\n\n return null;\n}\n", "'use client';\n\nimport * as React from 'react';\nimport { useChangelogContext } from '../context';\n\ntype Position = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw' | 'center';\n\nexport interface ChangelogEntriesListDropdownProps {\n children: React.ReactElement;\n position?: Position;\n}\n\n/**\n * ChangelogEntriesListDropdown - Renders a dropdown list of changelog entries\n *\n * This component wraps a child element (trigger) and opens the dropdown\n * when the child is clicked. Must be used within a ChangelogProvider.\n */\nexport function ChangelogEntriesListDropdown({\n children,\n position,\n}: ChangelogEntriesListDropdownProps) {\n const { store, module, theme, base, slug } = useChangelogContext();\n const widgetRef = React.useRef<{\n preload: () => void;\n open: () => void;\n destroy: () => void;\n setTheme: (t: string) => void;\n } | null>(null);\n const anchorId = React.useId();\n const cleanAnchorId = `sq-dropdown-${anchorId.replace(/:/g, '')}`;\n\n // Store initial theme in ref to use in creation\n const initialThemeRef = React.useRef(theme);\n\n // Create widget once on mount (theme changes handled separately via setTheme)\n React.useEffect(() => {\n const widget = module.createChangelogEntriesListDropdownWidget(\n `#${cleanAnchorId}`,\n store,\n {\n base,\n contentTheme: initialThemeRef.current,\n slug,\n position,\n }\n ) as {\n preload: () => void;\n open: () => void;\n destroy: () => void;\n setTheme: (t: string) => void;\n };\n\n widget.preload();\n widgetRef.current = widget;\n\n return () => {\n widget.destroy();\n widgetRef.current = null;\n };\n }, [slug, store, module, base, cleanAnchorId, position]);\n\n // Update theme when it changes (separate effect to avoid recreating widget)\n React.useEffect(() => {\n widgetRef.current?.setTheme(theme);\n }, [theme]);\n\n const handleClick = React.useCallback(() => {\n widgetRef.current?.open();\n }, []);\n\n // Clone the child and add the anchor id and click handler\n return React.cloneElement(children, {\n id: cleanAnchorId,\n onClick: (e: React.MouseEvent) => {\n const originalOnClick = children.props.onClick;\n if (originalOnClick) {\n originalOnClick(e);\n }\n handleClick();\n },\n });\n}\n", "'use client';\n\nimport * as React from 'react';\nimport { useChangelogContext } from '../context';\n\nexport interface ChangelogBannerProps {\n debug?: boolean;\n}\n\n/**\n * ChangelogBanner - Renders a banner for the latest changelog entry\n *\n * This component automatically fetches the latest changelog entry,\n * checks if it should be shown, and displays a banner at the bottom\n * of the screen. Must be used within a ChangelogProvider.\n */\nexport function ChangelogBanner({ debug = false }: ChangelogBannerProps) {\n const { store, module, theme, base, slug } = useChangelogContext();\n const widgetRef = React.useRef<{\n destroy: () => void;\n setTheme: (t: string) => void;\n } | null>(null);\n\n // Store initial theme in ref to use in creation\n const initialThemeRef = React.useRef(theme);\n\n // Create widget once on mount (theme changes handled separately via setTheme)\n React.useEffect(() => {\n let mounted = true;\n\n module\n .createChangelogBannerWidget(store, {\n base,\n contentTheme: initialThemeRef.current,\n slug,\n debug,\n })\n .then((widget) => {\n if (mounted && widget) {\n widgetRef.current = widget as {\n destroy: () => void;\n setTheme: (t: string) => void;\n };\n }\n });\n\n return () => {\n mounted = false;\n if (widgetRef.current) {\n widgetRef.current.destroy();\n widgetRef.current = null;\n }\n };\n }, [slug, store, module, base, debug]);\n\n // Update theme when it changes (separate effect to avoid recreating widget)\n React.useEffect(() => {\n widgetRef.current?.setTheme(theme);\n }, [theme]);\n\n return null;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "React", "React"]
7
7
  }