@growth-angels/ds-core 1.10.0 → 1.12.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.
@@ -1,10 +1,19 @@
1
1
  type ReactType = typeof import('react');
2
+ type ExtendedReactType = ReactType & {
3
+ createRoot: (container: Element | DocumentFragment) => {
4
+ render: (element: React.ReactElement) => void;
5
+ };
6
+ };
2
7
  declare global {
3
8
  interface Window {
4
9
  wp?: {
5
- element?: ReactType;
10
+ element?: ExtendedReactType & {
11
+ createRoot: (container: Element | DocumentFragment) => {
12
+ render: (element: React.ReactElement) => void;
13
+ };
14
+ };
6
15
  };
7
16
  }
8
17
  }
9
- export declare const useReactAdapter: () => ReactType;
18
+ export declare const useReactAdapter: () => ExtendedReactType;
10
19
  export {};
@@ -1,4 +1,3 @@
1
- import React from 'react';
2
1
  export const useReactAdapter = () => {
3
2
  // Check if WordPress element is available (WordPress context)
4
3
  if (typeof window !== 'undefined' && window.wp?.element) {
@@ -6,5 +5,5 @@ export const useReactAdapter = () => {
6
5
  }
7
6
  // Fallback for non-WordPress environments (Storybook, tests, SSR)
8
7
  // This will bundle React only in non-WordPress builds
9
- return React;
8
+ return import('react');
10
9
  };
@@ -5,6 +5,7 @@ export const GridItem = (props) => {
5
5
  sm: 12,
6
6
  md: 12,
7
7
  lg: 12,
8
+ xl: 12,
8
9
  }, style: givenStyle, extraClassNames, } = props;
9
10
  const style = {
10
11
  ...Object.fromEntries(Object.entries(sizes).map(([key, value]) => [`--ga-ds-grid-item-size-${key}`, `${value}`])),
@@ -0,0 +1 @@
1
+ export declare function HydrateCarousel(islands: NodeListOf<Element> | null): void;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Carousel } from "../organisms/Carousel/Carousel";
3
+ import { useReactAdapter } from "../hooks/useReactAdaptater";
4
+ import { NativeChildWrapper } from "./utils/native-child-wrapper";
5
+ const { createElement, createRoot, useRef, useEffect } = useReactAdapter();
6
+ export function HydrateCarousel(islands) {
7
+ console.log("HydrateCarousel called with islands:", islands);
8
+ islands?.forEach((carousel) => {
9
+ const Component = Carousel;
10
+ if (!Component)
11
+ return;
12
+ const props = carousel.getAttribute("data-props");
13
+ carousel.removeAttribute("data-props");
14
+ const parsedProps = JSON.parse(props || "{}");
15
+ const children = Array.from(carousel.children).map((child) => {
16
+ return _jsx(NativeChildWrapper, { child: child }, child.id);
17
+ });
18
+ const root = createRoot(carousel);
19
+ root.render(createElement(Component, { ...parsedProps, children }));
20
+ });
21
+ }
@@ -0,0 +1 @@
1
+ export declare function HydrateSpoiler(islands: NodeListOf<Element> | null): void;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Spoiler } from "../molecules/molecules";
3
+ import { SpoilerList } from "../organisms/organisms";
4
+ import { useReactAdapter } from "../hooks/useReactAdaptater";
5
+ const { createRoot } = useReactAdapter();
6
+ export function HydrateSpoiler(islands) {
7
+ islands?.forEach((el) => {
8
+ const props = el.getAttribute("data-props");
9
+ el.removeAttribute("data-props");
10
+ const items = Array.from(el.querySelectorAll('div[data-wp-island="ga-ds-spoiler"]')).map((item) => {
11
+ const props = item.getAttribute("data-props");
12
+ return (_jsx(Spoiler, { ...(props ? JSON.parse(props) : {}), children: _jsx("div", { dangerouslySetInnerHTML: {
13
+ __html: item.innerHTML,
14
+ } }) }));
15
+ });
16
+ const root = createRoot(el);
17
+ root.render(_jsx(SpoilerList, { ...(props ? JSON.parse(props) : {}), children: items }));
18
+ });
19
+ }
@@ -0,0 +1 @@
1
+ export declare function HydrateTabs(els: NodeListOf<Element> | null): void;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Tabs } from "@growth-angels/ds-core";
3
+ import { NativeChildWrapper } from "./utils/native-child-wrapper";
4
+ import { useReactAdapter } from "../hooks/useReactAdaptater";
5
+ const { createRoot } = useReactAdapter();
6
+ export function HydrateTabs(els) {
7
+ els?.forEach((el) => {
8
+ const props = el.getAttribute("data-props");
9
+ el.removeAttribute("data-props");
10
+ el.removeAttribute("data-wp-island");
11
+ const tabs = (props ? JSON.parse(props) : {}).tabs || [];
12
+ const extraClassNames = (props ? JSON.parse(props) : {}).extraClassNames || "";
13
+ // On récupère les panels réels, sans les écraser :
14
+ const panelEls = Array.from(el.querySelectorAll('div[data-wp-island="ga-ds-tab-panel"]'));
15
+ // On crée un tableau de wrappers React
16
+ const tabPanels = panelEls.map((panel) => {
17
+ const id = panel.getAttribute("id") || "";
18
+ // On crée un conteneur vide dans React
19
+ return _jsx(NativeChildWrapper, { id: id, child: panel }, id);
20
+ });
21
+ const root = createRoot(el);
22
+ root.render(_jsx(Tabs, { tabs: tabs, extraClassNames: extraClassNames, children: tabPanels }));
23
+ });
24
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./hydrate-carousel";
2
+ export * from "./hydrate-spoiler";
3
+ export * from "./hydrate-tabs";
@@ -0,0 +1,3 @@
1
+ export * from "./hydrate-carousel";
2
+ export * from "./hydrate-spoiler";
3
+ export * from "./hydrate-tabs";
@@ -0,0 +1,4 @@
1
+ export declare function NativeChildWrapper({ child, id }: {
2
+ child: Element;
3
+ id?: string;
4
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useReactAdapter } from "../../hooks/useReactAdaptater";
3
+ const { useRef, useEffect } = useReactAdapter();
4
+ export function NativeChildWrapper({ child, id }) {
5
+ const ref = useRef(null);
6
+ useEffect(() => {
7
+ if (ref.current) {
8
+ ref.current.appendChild(child); // on déplace l'élément natif
9
+ }
10
+ }, [child]);
11
+ return _jsx("div", { id: id, ref: ref });
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-angels/ds-core",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "description": "Design system by Growth Angels",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -16,6 +16,10 @@
16
16
  "import": "./dist/index.js",
17
17
  "types": "./dist/index.d.ts"
18
18
  },
19
+ "./lib": {
20
+ "import": "./dist/lib/index.js",
21
+ "types": "./dist/lib/index.d.ts"
22
+ },
19
23
  "./styles": "./src/styles.ts",
20
24
  "./styles/scss": "./src/index.scss",
21
25
  "./mixins": "./src/mixins.scss"
@@ -1,17 +1,25 @@
1
- import React from 'react'
2
-
3
1
  // @ts-ignore - React types from window.wp.element
4
2
  type ReactType = typeof import('react')
5
3
 
4
+ type ExtendedReactType = ReactType & {
5
+ createRoot: (container: Element | DocumentFragment) => {
6
+ render: (element: React.ReactElement) => void
7
+ }
8
+ }
9
+
6
10
  declare global {
7
11
  interface Window {
8
12
  wp?: {
9
- element?: ReactType
13
+ element?: ExtendedReactType & {
14
+ createRoot: (container: Element | DocumentFragment) => {
15
+ render: (element: React.ReactElement) => void
16
+ }
17
+ }
10
18
  }
11
19
  }
12
20
  }
13
21
 
14
- export const useReactAdapter = (): ReactType => {
22
+ export const useReactAdapter = (): ExtendedReactType => {
15
23
  // Check if WordPress element is available (WordPress context)
16
24
  if (typeof window !== 'undefined' && window.wp?.element) {
17
25
  return window.wp.element
@@ -19,6 +27,6 @@ export const useReactAdapter = (): ReactType => {
19
27
 
20
28
  // Fallback for non-WordPress environments (Storybook, tests, SSR)
21
29
  // This will bundle React only in non-WordPress builds
22
- return React
30
+ return import('react') as unknown as ExtendedReactType
23
31
  }
24
32
 
@@ -6,6 +6,7 @@
6
6
  .ga-ds-grid-item {
7
7
  --flex-size: var(--ga-ds-grid-item-size-xs);
8
8
  flex: 0 0 calc(100% * var(--flex-size) / map.get($ga-grid, "columns"));
9
+ max-width: calc(100% * var(--flex-size) / map.get($ga-grid, "columns"));
9
10
  padding-left: calc(map.get($ga-grid, "gutter-width") / 2);
10
11
  padding-right: calc(map.get($ga-grid, "gutter-width") / 2);
11
12
  margin-bottom: map.get($ga-grid, "gutter-width");
@@ -22,6 +23,10 @@
22
23
  --flex-size: var(--ga-ds-grid-item-size-lg);
23
24
  }
24
25
 
26
+ @include bp-up(xl, $ga-breakpoints) {
27
+ --flex-size: var(--ga-ds-grid-item-size-xl);
28
+ }
29
+
25
30
  > figure {
26
31
  width: 100%;
27
32
  img {
@@ -8,6 +8,7 @@ export const GridItem = (props: GridItemProps): JSX.Element => {
8
8
  sm: 12,
9
9
  md: 12,
10
10
  lg: 12,
11
+ xl: 12,
11
12
  },
12
13
  style: givenStyle,
13
14
  extraClassNames,
@@ -0,0 +1,24 @@
1
+ import { Carousel } from "../organisms/Carousel/Carousel"
2
+ import { useReactAdapter } from "../hooks/useReactAdaptater"
3
+ import { NativeChildWrapper } from "./utils/native-child-wrapper"
4
+ const { createElement, createRoot, useRef, useEffect } = useReactAdapter()
5
+
6
+ export function HydrateCarousel(islands: NodeListOf<Element> | null) {
7
+ console.log("HydrateCarousel called with islands:", islands)
8
+ islands?.forEach((carousel) => {
9
+ const Component = Carousel
10
+ if (!Component) return
11
+ const props = carousel.getAttribute("data-props")
12
+ carousel.removeAttribute("data-props")
13
+
14
+ const parsedProps = JSON.parse(props || "{}")
15
+
16
+ const children = Array.from(carousel.children).map((child) => {
17
+ return <NativeChildWrapper key={child.id} child={child} />
18
+ })
19
+
20
+ const root = createRoot(carousel)
21
+
22
+ root.render(createElement(Component, { ...parsedProps, children }))
23
+ })
24
+ }
@@ -0,0 +1,25 @@
1
+ import { Spoiler } from "../molecules/molecules"
2
+ import { SpoilerList } from "../organisms/organisms"
3
+ import { useReactAdapter } from "../hooks/useReactAdaptater"
4
+ const { createRoot } = useReactAdapter()
5
+
6
+ export function HydrateSpoiler(islands: NodeListOf<Element> | null) {
7
+ islands?.forEach((el) => {
8
+ const props = el.getAttribute("data-props")
9
+ el.removeAttribute("data-props")
10
+ const items = Array.from(el.querySelectorAll('div[data-wp-island="ga-ds-spoiler"]')).map((item) => {
11
+ const props = item.getAttribute("data-props")
12
+ return (
13
+ <Spoiler {...(props ? JSON.parse(props) : {})}>
14
+ <div
15
+ dangerouslySetInnerHTML={{
16
+ __html: item.innerHTML,
17
+ }}
18
+ ></div>
19
+ </Spoiler>
20
+ )
21
+ })
22
+ const root = createRoot(el)
23
+ root.render(<SpoilerList {...(props ? JSON.parse(props) : {})}>{items}</SpoilerList>)
24
+ })
25
+ }
@@ -0,0 +1,32 @@
1
+ import { Tabs } from "@growth-angels/ds-core"
2
+ import { NativeChildWrapper } from "./utils/native-child-wrapper"
3
+ import { useReactAdapter } from "../hooks/useReactAdaptater"
4
+ const { createRoot } = useReactAdapter()
5
+
6
+ export function HydrateTabs(els: NodeListOf<Element> | null) {
7
+ els?.forEach((el) => {
8
+ const props = el.getAttribute("data-props")
9
+ el.removeAttribute("data-props")
10
+ el.removeAttribute("data-wp-island")
11
+ const tabs = (props ? JSON.parse(props) : {}).tabs || []
12
+ const extraClassNames = (props ? JSON.parse(props) : {}).extraClassNames || ""
13
+
14
+ // On récupère les panels réels, sans les écraser :
15
+ const panelEls = Array.from(el.querySelectorAll('div[data-wp-island="ga-ds-tab-panel"]'))
16
+
17
+ // On crée un tableau de wrappers React
18
+ const tabPanels = panelEls.map((panel) => {
19
+ const id = panel.getAttribute("id") || ""
20
+
21
+ // On crée un conteneur vide dans React
22
+ return <NativeChildWrapper key={id} id={id} child={panel} />
23
+ })
24
+
25
+ const root = createRoot(el)
26
+ root.render(
27
+ <Tabs tabs={tabs} extraClassNames={extraClassNames}>
28
+ {tabPanels}
29
+ </Tabs>
30
+ )
31
+ })
32
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./hydrate-carousel"
2
+ export * from "./hydrate-spoiler"
3
+ export * from "./hydrate-tabs"
@@ -0,0 +1,14 @@
1
+ import { useReactAdapter } from "../../hooks/useReactAdaptater"
2
+ const { useRef, useEffect } = useReactAdapter()
3
+
4
+ export function NativeChildWrapper({ child, id }: { child: Element; id?: string }) {
5
+ const ref = useRef<HTMLDivElement | null>(null)
6
+
7
+ useEffect(() => {
8
+ if (ref.current) {
9
+ ref.current.appendChild(child) // on déplace l'élément natif
10
+ }
11
+ }, [child])
12
+
13
+ return <div id={id} ref={ref} />
14
+ }