@squeletteapp/widget-react 0.1.1 → 1.1.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/components/changelog-banner.d.ts +11 -0
- package/dist/components/changelog-banner.js +44 -0
- package/dist/components/changelog-entries-list-dropdown.d.ts +14 -0
- package/dist/components/changelog-entries-list-dropdown.js +50 -0
- package/dist/components/changelog-entry-modal.d.ts +11 -0
- package/dist/components/changelog-entry-modal.js +34 -0
- package/dist/context.d.ts +53 -0
- package/dist/context.js +41 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.esm.js +133 -334
- package/dist/index.esm.js.map +4 -4
- package/dist/index.js +132 -321
- package/dist/index.js.map +4 -4
- package/dist/types.d.ts +1 -0
- package/dist/types.js +1 -0
- package/package.json +7 -5
- package/dist/components.d.ts +0 -27
- package/dist/components.js +0 -39
- package/dist/hooks.d.ts +0 -20
- package/dist/hooks.js +0 -143
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ChangelogBannerProps {
|
|
2
|
+
debug?: boolean;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* ChangelogBanner - Renders a banner for the latest changelog entry
|
|
6
|
+
*
|
|
7
|
+
* This component automatically fetches the latest changelog entry,
|
|
8
|
+
* checks if it should be shown, and displays a banner at the bottom
|
|
9
|
+
* of the screen. Must be used within a ChangelogProvider.
|
|
10
|
+
*/
|
|
11
|
+
export declare function ChangelogBanner({ debug }: ChangelogBannerProps): null;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { useChangelogContext } from '../context';
|
|
4
|
+
/**
|
|
5
|
+
* ChangelogBanner - Renders a banner for the latest changelog entry
|
|
6
|
+
*
|
|
7
|
+
* This component automatically fetches the latest changelog entry,
|
|
8
|
+
* checks if it should be shown, and displays a banner at the bottom
|
|
9
|
+
* of the screen. Must be used within a ChangelogProvider.
|
|
10
|
+
*/
|
|
11
|
+
export function ChangelogBanner({ debug = false }) {
|
|
12
|
+
const { store, module, theme, base, slug } = useChangelogContext();
|
|
13
|
+
const widgetRef = React.useRef(null);
|
|
14
|
+
// Store initial theme in ref to use in creation
|
|
15
|
+
const initialThemeRef = React.useRef(theme);
|
|
16
|
+
// Create widget once on mount (theme changes handled separately via setTheme)
|
|
17
|
+
React.useEffect(() => {
|
|
18
|
+
let mounted = true;
|
|
19
|
+
module
|
|
20
|
+
.createChangelogBannerWidget(store, {
|
|
21
|
+
base,
|
|
22
|
+
contentTheme: initialThemeRef.current,
|
|
23
|
+
slug,
|
|
24
|
+
debug,
|
|
25
|
+
})
|
|
26
|
+
.then((widget) => {
|
|
27
|
+
if (mounted && widget) {
|
|
28
|
+
widgetRef.current = widget;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return () => {
|
|
32
|
+
mounted = false;
|
|
33
|
+
if (widgetRef.current) {
|
|
34
|
+
widgetRef.current.destroy();
|
|
35
|
+
widgetRef.current = null;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}, [slug, store, module, base, debug]);
|
|
39
|
+
// Update theme when it changes (separate effect to avoid recreating widget)
|
|
40
|
+
React.useEffect(() => {
|
|
41
|
+
widgetRef.current?.setTheme(theme);
|
|
42
|
+
}, [theme]);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
type Position = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw' | 'center';
|
|
3
|
+
export interface ChangelogEntriesListDropdownProps {
|
|
4
|
+
children: React.ReactElement;
|
|
5
|
+
position?: Position;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* ChangelogEntriesListDropdown - Renders a dropdown list of changelog entries
|
|
9
|
+
*
|
|
10
|
+
* This component wraps a child element (trigger) and opens the dropdown
|
|
11
|
+
* when the child is clicked. Must be used within a ChangelogProvider.
|
|
12
|
+
*/
|
|
13
|
+
export declare function ChangelogEntriesListDropdown({ children, position, }: ChangelogEntriesListDropdownProps): React.ReactElement<any, string | React.JSXElementConstructor<any>>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { useChangelogContext } from '../context';
|
|
4
|
+
/**
|
|
5
|
+
* ChangelogEntriesListDropdown - Renders a dropdown list of changelog entries
|
|
6
|
+
*
|
|
7
|
+
* This component wraps a child element (trigger) and opens the dropdown
|
|
8
|
+
* when the child is clicked. Must be used within a ChangelogProvider.
|
|
9
|
+
*/
|
|
10
|
+
export function ChangelogEntriesListDropdown({ children, position, }) {
|
|
11
|
+
const { store, module, theme, base, slug } = useChangelogContext();
|
|
12
|
+
const widgetRef = React.useRef(null);
|
|
13
|
+
const anchorId = React.useId();
|
|
14
|
+
const cleanAnchorId = `sq-dropdown-${anchorId.replace(/:/g, '')}`;
|
|
15
|
+
// Store initial theme in ref to use in creation
|
|
16
|
+
const initialThemeRef = React.useRef(theme);
|
|
17
|
+
// Create widget once on mount (theme changes handled separately via setTheme)
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
const widget = module.createChangelogEntriesListDropdownWidget(`#${cleanAnchorId}`, store, {
|
|
20
|
+
base,
|
|
21
|
+
contentTheme: initialThemeRef.current,
|
|
22
|
+
slug,
|
|
23
|
+
position,
|
|
24
|
+
});
|
|
25
|
+
widget.preload();
|
|
26
|
+
widgetRef.current = widget;
|
|
27
|
+
return () => {
|
|
28
|
+
widget.destroy();
|
|
29
|
+
widgetRef.current = null;
|
|
30
|
+
};
|
|
31
|
+
}, [slug, store, module, base, cleanAnchorId, position]);
|
|
32
|
+
// Update theme when it changes (separate effect to avoid recreating widget)
|
|
33
|
+
React.useEffect(() => {
|
|
34
|
+
widgetRef.current?.setTheme(theme);
|
|
35
|
+
}, [theme]);
|
|
36
|
+
const handleClick = React.useCallback(() => {
|
|
37
|
+
widgetRef.current?.open();
|
|
38
|
+
}, []);
|
|
39
|
+
// Clone the child and add the anchor id and click handler
|
|
40
|
+
return React.cloneElement(children, {
|
|
41
|
+
id: cleanAnchorId,
|
|
42
|
+
onClick: (e) => {
|
|
43
|
+
const originalOnClick = children.props.onClick;
|
|
44
|
+
if (originalOnClick) {
|
|
45
|
+
originalOnClick(e);
|
|
46
|
+
}
|
|
47
|
+
handleClick();
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ChangelogEntryModalProps {
|
|
2
|
+
ticketId: string;
|
|
3
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* ChangelogEntryModal - Renders a modal for a single changelog entry
|
|
7
|
+
*
|
|
8
|
+
* This component manages its own widget lifecycle and automatically
|
|
9
|
+
* cleans up on unmount. Must be used within a ChangelogProvider.
|
|
10
|
+
*/
|
|
11
|
+
export declare function ChangelogEntryModal({ ticketId, onOpenChange, }: ChangelogEntryModalProps): null;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { useChangelogContext } from '../context';
|
|
4
|
+
/**
|
|
5
|
+
* ChangelogEntryModal - Renders a modal for a single changelog entry
|
|
6
|
+
*
|
|
7
|
+
* This component manages its own widget lifecycle and automatically
|
|
8
|
+
* cleans up on unmount. Must be used within a ChangelogProvider.
|
|
9
|
+
*/
|
|
10
|
+
export function ChangelogEntryModal({ ticketId, onOpenChange, }) {
|
|
11
|
+
const { store, module, theme, base, slug } = useChangelogContext();
|
|
12
|
+
const widgetRef = React.useRef(null);
|
|
13
|
+
React.useEffect(() => {
|
|
14
|
+
const widget = module.createChangelogEntryWidget(ticketId, {
|
|
15
|
+
base,
|
|
16
|
+
contentTheme: theme,
|
|
17
|
+
slug,
|
|
18
|
+
});
|
|
19
|
+
if (onOpenChange) {
|
|
20
|
+
widget.onOpenChange(onOpenChange);
|
|
21
|
+
}
|
|
22
|
+
widgetRef.current = widget;
|
|
23
|
+
store.mount(ticketId, widget);
|
|
24
|
+
return () => {
|
|
25
|
+
store.unmount(ticketId);
|
|
26
|
+
widgetRef.current = null;
|
|
27
|
+
};
|
|
28
|
+
}, [ticketId, slug, store, module, base, onOpenChange, theme]);
|
|
29
|
+
// Update theme when it changes
|
|
30
|
+
React.useEffect(() => {
|
|
31
|
+
widgetRef.current?.setTheme(theme);
|
|
32
|
+
}, [theme]);
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ContentTheme } from './types';
|
|
3
|
+
type WidgetStore = {
|
|
4
|
+
getState: () => Record<string, unknown>;
|
|
5
|
+
mount: (source: string, widget: unknown) => Promise<void>;
|
|
6
|
+
unmount: (source: string) => void;
|
|
7
|
+
open: (source: string) => Promise<void>;
|
|
8
|
+
setTheme: (theme: ContentTheme) => void;
|
|
9
|
+
};
|
|
10
|
+
type WidgetModule = {
|
|
11
|
+
createChangelogStore: () => WidgetStore;
|
|
12
|
+
createChangelogEntryWidget: (ticketId: string, options: {
|
|
13
|
+
base?: string;
|
|
14
|
+
contentTheme?: ContentTheme;
|
|
15
|
+
slug?: string;
|
|
16
|
+
}) => unknown;
|
|
17
|
+
createChangelogBannerWidget: (store: WidgetStore, options: {
|
|
18
|
+
base?: string;
|
|
19
|
+
contentTheme?: ContentTheme;
|
|
20
|
+
slug: string;
|
|
21
|
+
debug?: boolean;
|
|
22
|
+
}) => Promise<unknown>;
|
|
23
|
+
createChangelogEntriesListDropdownWidget: (anchor: string, store: WidgetStore, options: {
|
|
24
|
+
base?: string;
|
|
25
|
+
contentTheme?: ContentTheme;
|
|
26
|
+
slug?: string;
|
|
27
|
+
position?: 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw' | 'center';
|
|
28
|
+
}) => unknown;
|
|
29
|
+
};
|
|
30
|
+
type ChangelogContextValue = {
|
|
31
|
+
store: WidgetStore;
|
|
32
|
+
module: WidgetModule;
|
|
33
|
+
theme: ContentTheme;
|
|
34
|
+
base?: string;
|
|
35
|
+
slug: string;
|
|
36
|
+
};
|
|
37
|
+
export interface ChangelogProviderProps {
|
|
38
|
+
children: React.ReactNode;
|
|
39
|
+
slug: string;
|
|
40
|
+
theme?: ContentTheme;
|
|
41
|
+
base?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* ChangelogProvider - Provides changelog store and configuration to child components
|
|
45
|
+
*
|
|
46
|
+
* This provider handles:
|
|
47
|
+
* - Creating and managing the widget store (client-side only)
|
|
48
|
+
* - Syncing theme changes to all widgets
|
|
49
|
+
* - Providing base URL and slug to all child components
|
|
50
|
+
*/
|
|
51
|
+
export declare function ChangelogProvider({ children, slug, theme, base, }: ChangelogProviderProps): import("react/jsx-runtime").JSX.Element | null;
|
|
52
|
+
export declare function useChangelogContext(): ChangelogContextValue;
|
|
53
|
+
export {};
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
const ChangelogContext = React.createContext(null);
|
|
5
|
+
/**
|
|
6
|
+
* ChangelogProvider - Provides changelog store and configuration to child components
|
|
7
|
+
*
|
|
8
|
+
* This provider handles:
|
|
9
|
+
* - Creating and managing the widget store (client-side only)
|
|
10
|
+
* - Syncing theme changes to all widgets
|
|
11
|
+
* - Providing base URL and slug to all child components
|
|
12
|
+
*/
|
|
13
|
+
export function ChangelogProvider({ children, slug, theme = 'light', base, }) {
|
|
14
|
+
const [context, setContext] = React.useState(null);
|
|
15
|
+
// Initialize store on client side only
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
import('@squeletteapp/widget').then((mod) => {
|
|
18
|
+
const widgetModule = mod;
|
|
19
|
+
setContext({
|
|
20
|
+
store: widgetModule.createChangelogStore(),
|
|
21
|
+
module: widgetModule,
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}, []);
|
|
25
|
+
// Update theme when it changes
|
|
26
|
+
React.useEffect(() => {
|
|
27
|
+
context?.store.setTheme(theme);
|
|
28
|
+
}, [context, theme]);
|
|
29
|
+
// Don't render children until store is ready (client-side only)
|
|
30
|
+
if (!context) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return (_jsx(ChangelogContext.Provider, { value: { store: context.store, module: context.module, theme, base, slug }, children: children }));
|
|
34
|
+
}
|
|
35
|
+
export function useChangelogContext() {
|
|
36
|
+
const context = React.useContext(ChangelogContext);
|
|
37
|
+
if (!context) {
|
|
38
|
+
throw new Error('useChangelogContext must be used within a ChangelogProvider');
|
|
39
|
+
}
|
|
40
|
+
return context;
|
|
41
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
1
|
+
export { ChangelogProvider, useChangelogContext, type ChangelogProviderProps, } from './context';
|
|
2
|
+
export { ChangelogEntryModal, type ChangelogEntryModalProps, } from './components/changelog-entry-modal';
|
|
3
|
+
export { ChangelogEntriesListDropdown, type ChangelogEntriesListDropdownProps, } from './components/changelog-entries-list-dropdown';
|
|
4
|
+
export { ChangelogBanner, type ChangelogBannerProps, } from './components/changelog-banner';
|
|
5
|
+
export type { ContentTheme } from './types';
|