@cmssy/react 0.2.5 → 0.3.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/client.cjs CHANGED
@@ -750,6 +750,16 @@ function CmssyLazyLayout({ load, ...props }) {
750
750
  if (!blocks) return null;
751
751
  return /* @__PURE__ */ jsxRuntime.jsx(CmssyEditableLayout, { ...props, blocks });
752
752
  }
753
+ var LocaleContext = react.createContext(null);
754
+ function CmssyLocaleProvider({
755
+ value,
756
+ children
757
+ }) {
758
+ return /* @__PURE__ */ jsxRuntime.jsx(LocaleContext.Provider, { value, children });
759
+ }
760
+ function useCmssyLocale() {
761
+ return react.useContext(LocaleContext);
762
+ }
753
763
  var CmssyAuthContext = react.createContext(null);
754
764
  function CmssyAuthProvider({
755
765
  children,
@@ -1462,6 +1472,7 @@ exports.CmssyEditableLayout = CmssyEditableLayout;
1462
1472
  exports.CmssyEditablePage = CmssyEditablePage;
1463
1473
  exports.CmssyLazyEditor = CmssyLazyEditor;
1464
1474
  exports.CmssyLazyLayout = CmssyLazyLayout;
1475
+ exports.CmssyLocaleProvider = CmssyLocaleProvider;
1465
1476
  exports.cartBlock = cartBlock;
1466
1477
  exports.checkoutBlock = checkoutBlock;
1467
1478
  exports.formatPrice = formatPrice;
@@ -1470,6 +1481,7 @@ exports.fromMinorUnits = fromMinorUnits;
1470
1481
  exports.productBlock = productBlock;
1471
1482
  exports.toMinorUnits = toMinorUnits;
1472
1483
  exports.useCart = useCart;
1484
+ exports.useCmssyLocale = useCmssyLocale;
1473
1485
  exports.useCmssyOrders = useCmssyOrders;
1474
1486
  exports.useCmssyUser = useCmssyUser;
1475
1487
  exports.useEditBridge = useEditBridge;
package/dist/client.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { B as BlockSchema, a as BlockMeta, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, e as CmssyCart, f as CmssyOrder, g as CmssyProduct } from './commerce-queries-BYx7uUnE.cjs';
3
- export { h as CmssyCartDiscount, i as CmssyCartItem, j as CmssyCartItemSnapshot, k as CmssyOrderItem, l as CmssyProductVariant } from './commerce-queries-BYx7uUnE.cjs';
2
+ import { B as BlockSchema, a as BlockMeta, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, e as CmssyLocaleContext, f as CmssyCart, g as CmssyOrder, h as CmssyProduct } from './commerce-queries-CqCdTD31.cjs';
3
+ export { i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, l as CmssyOrderItem, m as CmssyProductVariant } from './commerce-queries-CqCdTD31.cjs';
4
4
  import { ReactNode } from 'react';
5
5
 
6
6
  interface EditBridgeConfig {
@@ -81,6 +81,19 @@ interface CmssyLazyLayoutProps {
81
81
  }
82
82
  declare function CmssyLazyLayout({ load, ...props }: CmssyLazyLayoutProps): react_jsx_runtime.JSX.Element | null;
83
83
 
84
+ interface CmssyLocaleProviderProps {
85
+ value: CmssyLocaleContext;
86
+ children: ReactNode;
87
+ }
88
+ /**
89
+ * Exposes the active locale ({@link CmssyLocaleContext}) to client components
90
+ * below it (e.g. `CmssyLink`) so they can build locale-aware hrefs without
91
+ * prop-drilling. Wrap your root layout body with it.
92
+ */
93
+ declare function CmssyLocaleProvider({ value, children, }: CmssyLocaleProviderProps): react_jsx_runtime.JSX.Element;
94
+ /** Reads the active locale; returns null when no provider is mounted. */
95
+ declare function useCmssyLocale(): CmssyLocaleContext | null;
96
+
84
97
  interface CmssyAuthUser {
85
98
  recordId: string;
86
99
  email: string;
@@ -156,4 +169,4 @@ declare function fromMinorUnits(minor: number, currency: string): number;
156
169
  declare function toMinorUnits(amount: number, currency: string): number;
157
170
  declare function formatPrice(minor: number, currency: string | null | undefined): string;
158
171
 
159
- export { type CmssyAddToCartOptions, type CmssyAuthActionResult, CmssyAuthProvider, type CmssyAuthProviderProps, type CmssyAuthState, type CmssyAuthUser, CmssyCart, CmssyCommerceProvider, type CmssyCommerceProviderProps, type CmssyCommerceState, CmssyEditableLayout, type CmssyEditableLayoutProps, CmssyEditablePage, type CmssyEditablePageProps, CmssyLazyEditor, type CmssyLazyEditorProps, CmssyLazyLayout, type CmssyLazyLayoutProps, CmssyOrder, type CmssyOrdersState, CmssyProduct, type EditBridgeConfig, type EditBridgeState, type PatchMap, type UseCmssyOrdersOptions, cartBlock, checkoutBlock, formatPrice, fractionDigits, fromMinorUnits, productBlock, toMinorUnits, useCart, useCmssyOrders, useCmssyUser, useEditBridge };
172
+ export { type CmssyAddToCartOptions, type CmssyAuthActionResult, CmssyAuthProvider, type CmssyAuthProviderProps, type CmssyAuthState, type CmssyAuthUser, CmssyCart, CmssyCommerceProvider, type CmssyCommerceProviderProps, type CmssyCommerceState, CmssyEditableLayout, type CmssyEditableLayoutProps, CmssyEditablePage, type CmssyEditablePageProps, CmssyLazyEditor, type CmssyLazyEditorProps, CmssyLazyLayout, type CmssyLazyLayoutProps, CmssyLocaleProvider, type CmssyLocaleProviderProps, CmssyOrder, type CmssyOrdersState, CmssyProduct, type EditBridgeConfig, type EditBridgeState, type PatchMap, type UseCmssyOrdersOptions, cartBlock, checkoutBlock, formatPrice, fractionDigits, fromMinorUnits, productBlock, toMinorUnits, useCart, useCmssyLocale, useCmssyOrders, useCmssyUser, useEditBridge };
package/dist/client.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { B as BlockSchema, a as BlockMeta, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, e as CmssyCart, f as CmssyOrder, g as CmssyProduct } from './commerce-queries-BYx7uUnE.js';
3
- export { h as CmssyCartDiscount, i as CmssyCartItem, j as CmssyCartItemSnapshot, k as CmssyOrderItem, l as CmssyProductVariant } from './commerce-queries-BYx7uUnE.js';
2
+ import { B as BlockSchema, a as BlockMeta, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, e as CmssyLocaleContext, f as CmssyCart, g as CmssyOrder, h as CmssyProduct } from './commerce-queries-CqCdTD31.js';
3
+ export { i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, l as CmssyOrderItem, m as CmssyProductVariant } from './commerce-queries-CqCdTD31.js';
4
4
  import { ReactNode } from 'react';
5
5
 
6
6
  interface EditBridgeConfig {
@@ -81,6 +81,19 @@ interface CmssyLazyLayoutProps {
81
81
  }
82
82
  declare function CmssyLazyLayout({ load, ...props }: CmssyLazyLayoutProps): react_jsx_runtime.JSX.Element | null;
83
83
 
84
+ interface CmssyLocaleProviderProps {
85
+ value: CmssyLocaleContext;
86
+ children: ReactNode;
87
+ }
88
+ /**
89
+ * Exposes the active locale ({@link CmssyLocaleContext}) to client components
90
+ * below it (e.g. `CmssyLink`) so they can build locale-aware hrefs without
91
+ * prop-drilling. Wrap your root layout body with it.
92
+ */
93
+ declare function CmssyLocaleProvider({ value, children, }: CmssyLocaleProviderProps): react_jsx_runtime.JSX.Element;
94
+ /** Reads the active locale; returns null when no provider is mounted. */
95
+ declare function useCmssyLocale(): CmssyLocaleContext | null;
96
+
84
97
  interface CmssyAuthUser {
85
98
  recordId: string;
86
99
  email: string;
@@ -156,4 +169,4 @@ declare function fromMinorUnits(minor: number, currency: string): number;
156
169
  declare function toMinorUnits(amount: number, currency: string): number;
157
170
  declare function formatPrice(minor: number, currency: string | null | undefined): string;
158
171
 
159
- export { type CmssyAddToCartOptions, type CmssyAuthActionResult, CmssyAuthProvider, type CmssyAuthProviderProps, type CmssyAuthState, type CmssyAuthUser, CmssyCart, CmssyCommerceProvider, type CmssyCommerceProviderProps, type CmssyCommerceState, CmssyEditableLayout, type CmssyEditableLayoutProps, CmssyEditablePage, type CmssyEditablePageProps, CmssyLazyEditor, type CmssyLazyEditorProps, CmssyLazyLayout, type CmssyLazyLayoutProps, CmssyOrder, type CmssyOrdersState, CmssyProduct, type EditBridgeConfig, type EditBridgeState, type PatchMap, type UseCmssyOrdersOptions, cartBlock, checkoutBlock, formatPrice, fractionDigits, fromMinorUnits, productBlock, toMinorUnits, useCart, useCmssyOrders, useCmssyUser, useEditBridge };
172
+ export { type CmssyAddToCartOptions, type CmssyAuthActionResult, CmssyAuthProvider, type CmssyAuthProviderProps, type CmssyAuthState, type CmssyAuthUser, CmssyCart, CmssyCommerceProvider, type CmssyCommerceProviderProps, type CmssyCommerceState, CmssyEditableLayout, type CmssyEditableLayoutProps, CmssyEditablePage, type CmssyEditablePageProps, CmssyLazyEditor, type CmssyLazyEditorProps, CmssyLazyLayout, type CmssyLazyLayoutProps, CmssyLocaleProvider, type CmssyLocaleProviderProps, CmssyOrder, type CmssyOrdersState, CmssyProduct, type EditBridgeConfig, type EditBridgeState, type PatchMap, type UseCmssyOrdersOptions, cartBlock, checkoutBlock, formatPrice, fractionDigits, fromMinorUnits, productBlock, toMinorUnits, useCart, useCmssyLocale, useCmssyOrders, useCmssyUser, useEditBridge };
package/dist/client.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { createContext, useState, useRef, useEffect, useMemo, useCallback, useContext, createElement } from 'react';
2
+ import { createContext, useState, useRef, useEffect, useMemo, useContext, useCallback, createElement } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
 
5
5
  // src/registry.ts
@@ -748,6 +748,16 @@ function CmssyLazyLayout({ load, ...props }) {
748
748
  if (!blocks) return null;
749
749
  return /* @__PURE__ */ jsx(CmssyEditableLayout, { ...props, blocks });
750
750
  }
751
+ var LocaleContext = createContext(null);
752
+ function CmssyLocaleProvider({
753
+ value,
754
+ children
755
+ }) {
756
+ return /* @__PURE__ */ jsx(LocaleContext.Provider, { value, children });
757
+ }
758
+ function useCmssyLocale() {
759
+ return useContext(LocaleContext);
760
+ }
751
761
  var CmssyAuthContext = createContext(null);
752
762
  function CmssyAuthProvider({
753
763
  children,
@@ -1454,4 +1464,4 @@ function useCmssyOrders(options = {}) {
1454
1464
  return { orders, total, hasMore, loading, error, refresh: load };
1455
1465
  }
1456
1466
 
1457
- export { CmssyAuthProvider, CmssyCommerceProvider, CmssyEditableLayout, CmssyEditablePage, CmssyLazyEditor, CmssyLazyLayout, cartBlock, checkoutBlock, formatPrice, fractionDigits, fromMinorUnits, productBlock, toMinorUnits, useCart, useCmssyOrders, useCmssyUser, useEditBridge };
1467
+ export { CmssyAuthProvider, CmssyCommerceProvider, CmssyEditableLayout, CmssyEditablePage, CmssyLazyEditor, CmssyLazyLayout, CmssyLocaleProvider, cartBlock, checkoutBlock, formatPrice, fractionDigits, fromMinorUnits, productBlock, toMinorUnits, useCart, useCmssyLocale, useCmssyOrders, useCmssyUser, useEditBridge };
@@ -372,6 +372,13 @@ interface CmssyOrderPayment {
372
372
  provider: string | null;
373
373
  at: string;
374
374
  }
375
+ interface CmssyOrderTaxSummaryLine {
376
+ rateId: string | null;
377
+ name: string | null;
378
+ rate: number;
379
+ base: number;
380
+ amount: number;
381
+ }
375
382
  interface CmssyOrder {
376
383
  id: string;
377
384
  status: string;
@@ -380,6 +387,8 @@ interface CmssyOrder {
380
387
  currency: string;
381
388
  customerEmail: string;
382
389
  tax?: number;
390
+ pricesIncludeTax?: boolean;
391
+ taxSummary?: CmssyOrderTaxSummaryLine[];
383
392
  refundedAmount?: number;
384
393
  items?: CmssyOrderItem[];
385
394
  paymentProvider?: string | null;
@@ -399,4 +408,4 @@ interface CmssyOrder {
399
408
  createdAt?: string;
400
409
  }
401
410
 
402
- export { defineBlock as $, type AppToEditorMessage as A, type BlockSchema as B, type CmssyPageData as C, type CmssyRecordList as D, type EditorToAppMessage as E, type FieldDefinition as F, type CmssySiteConfig as G, FORM_QUERY as H, type FetchLikeResponse as I, type FetchPageOptions as J, type FieldType as K, MODEL_RECORDS_QUERY as L, MODEL_DEFINITIONS_QUERY as M, type ParentReadyMessage as N, type PatchMessage as O, PROTOCOL_VERSION as P, type RawLayoutBlock as Q, type RawBlock as R, type ReadyMessage as S, SITE_CONFIG_QUERY as T, SUBMIT_FORM_MUTATION as U, type SelectMessage as V, type SubmitFormInput as W, blocksToMeta as X, blocksToSchemas as Y, buildBlockContext as Z, buildBlockMap as _, type BlockMeta as a, fetchLayouts as a0, fetchPage as a1, isProtocolCompatible as a2, normalizeSlug as a3, type BlockDefinition as b, type CmssyFormDefinition as c, type CmssyLayoutGroup as d, type CmssyCart as e, type CmssyOrder as f, type CmssyProduct as g, type CmssyCartDiscount as h, type CmssyCartItem as i, type CmssyCartItemSnapshot as j, type CmssyOrderItem as k, type CmssyProductVariant as l, type FetchLike as m, type CmssyClientConfig as n, type BlockMap as o, type CmssyBlockContext as p, type BlockRect as q, type BoundsMessage as r, type ClickMessage as s, type CmssyBranding as t, type CmssyFormField as u, type CmssyFormSettings as v, type CmssyFormSubmitResponse as w, type CmssyLocaleContext as x, type CmssyModelDefinition as y, type CmssyModelRecord as z };
411
+ export { defineBlock as $, type AppToEditorMessage as A, type BlockSchema as B, type CmssyPageData as C, type CmssyRecordList as D, type EditorToAppMessage as E, type FieldDefinition as F, type CmssySiteConfig as G, FORM_QUERY as H, type FetchLikeResponse as I, type FetchPageOptions as J, type FieldType as K, MODEL_RECORDS_QUERY as L, MODEL_DEFINITIONS_QUERY as M, type ParentReadyMessage as N, type PatchMessage as O, PROTOCOL_VERSION as P, type RawLayoutBlock as Q, type RawBlock as R, type ReadyMessage as S, SITE_CONFIG_QUERY as T, SUBMIT_FORM_MUTATION as U, type SelectMessage as V, type SubmitFormInput as W, blocksToMeta as X, blocksToSchemas as Y, buildBlockContext as Z, buildBlockMap as _, type BlockMeta as a, fetchLayouts as a0, fetchPage as a1, isProtocolCompatible as a2, normalizeSlug as a3, type BlockDefinition as b, type CmssyFormDefinition as c, type CmssyLayoutGroup as d, type CmssyLocaleContext as e, type CmssyCart as f, type CmssyOrder as g, type CmssyProduct as h, type CmssyCartDiscount as i, type CmssyCartItem as j, type CmssyCartItemSnapshot as k, type CmssyOrderItem as l, type CmssyProductVariant as m, type FetchLike as n, type CmssyClientConfig as o, type BlockMap as p, type CmssyBlockContext as q, type BlockRect as r, type BoundsMessage as s, type ClickMessage as t, type CmssyBranding as u, type CmssyFormField as v, type CmssyFormSettings as w, type CmssyFormSubmitResponse as x, type CmssyModelDefinition as y, type CmssyModelRecord as z };
@@ -372,6 +372,13 @@ interface CmssyOrderPayment {
372
372
  provider: string | null;
373
373
  at: string;
374
374
  }
375
+ interface CmssyOrderTaxSummaryLine {
376
+ rateId: string | null;
377
+ name: string | null;
378
+ rate: number;
379
+ base: number;
380
+ amount: number;
381
+ }
375
382
  interface CmssyOrder {
376
383
  id: string;
377
384
  status: string;
@@ -380,6 +387,8 @@ interface CmssyOrder {
380
387
  currency: string;
381
388
  customerEmail: string;
382
389
  tax?: number;
390
+ pricesIncludeTax?: boolean;
391
+ taxSummary?: CmssyOrderTaxSummaryLine[];
383
392
  refundedAmount?: number;
384
393
  items?: CmssyOrderItem[];
385
394
  paymentProvider?: string | null;
@@ -399,4 +408,4 @@ interface CmssyOrder {
399
408
  createdAt?: string;
400
409
  }
401
410
 
402
- export { defineBlock as $, type AppToEditorMessage as A, type BlockSchema as B, type CmssyPageData as C, type CmssyRecordList as D, type EditorToAppMessage as E, type FieldDefinition as F, type CmssySiteConfig as G, FORM_QUERY as H, type FetchLikeResponse as I, type FetchPageOptions as J, type FieldType as K, MODEL_RECORDS_QUERY as L, MODEL_DEFINITIONS_QUERY as M, type ParentReadyMessage as N, type PatchMessage as O, PROTOCOL_VERSION as P, type RawLayoutBlock as Q, type RawBlock as R, type ReadyMessage as S, SITE_CONFIG_QUERY as T, SUBMIT_FORM_MUTATION as U, type SelectMessage as V, type SubmitFormInput as W, blocksToMeta as X, blocksToSchemas as Y, buildBlockContext as Z, buildBlockMap as _, type BlockMeta as a, fetchLayouts as a0, fetchPage as a1, isProtocolCompatible as a2, normalizeSlug as a3, type BlockDefinition as b, type CmssyFormDefinition as c, type CmssyLayoutGroup as d, type CmssyCart as e, type CmssyOrder as f, type CmssyProduct as g, type CmssyCartDiscount as h, type CmssyCartItem as i, type CmssyCartItemSnapshot as j, type CmssyOrderItem as k, type CmssyProductVariant as l, type FetchLike as m, type CmssyClientConfig as n, type BlockMap as o, type CmssyBlockContext as p, type BlockRect as q, type BoundsMessage as r, type ClickMessage as s, type CmssyBranding as t, type CmssyFormField as u, type CmssyFormSettings as v, type CmssyFormSubmitResponse as w, type CmssyLocaleContext as x, type CmssyModelDefinition as y, type CmssyModelRecord as z };
411
+ export { defineBlock as $, type AppToEditorMessage as A, type BlockSchema as B, type CmssyPageData as C, type CmssyRecordList as D, type EditorToAppMessage as E, type FieldDefinition as F, type CmssySiteConfig as G, FORM_QUERY as H, type FetchLikeResponse as I, type FetchPageOptions as J, type FieldType as K, MODEL_RECORDS_QUERY as L, MODEL_DEFINITIONS_QUERY as M, type ParentReadyMessage as N, type PatchMessage as O, PROTOCOL_VERSION as P, type RawLayoutBlock as Q, type RawBlock as R, type ReadyMessage as S, SITE_CONFIG_QUERY as T, SUBMIT_FORM_MUTATION as U, type SelectMessage as V, type SubmitFormInput as W, blocksToMeta as X, blocksToSchemas as Y, buildBlockContext as Z, buildBlockMap as _, type BlockMeta as a, fetchLayouts as a0, fetchPage as a1, isProtocolCompatible as a2, normalizeSlug as a3, type BlockDefinition as b, type CmssyFormDefinition as c, type CmssyLayoutGroup as d, type CmssyLocaleContext as e, type CmssyCart as f, type CmssyOrder as g, type CmssyProduct as h, type CmssyCartDiscount as i, type CmssyCartItem as j, type CmssyCartItemSnapshot as k, type CmssyOrderItem as l, type CmssyProductVariant as m, type FetchLike as n, type CmssyClientConfig as o, type BlockMap as p, type CmssyBlockContext as q, type BlockRect as r, type BoundsMessage as s, type ClickMessage as t, type CmssyBranding as u, type CmssyFormField as v, type CmssyFormSettings as w, type CmssyFormSubmitResponse as x, type CmssyModelDefinition as y, type CmssyModelRecord as z };
package/dist/index.cjs CHANGED
@@ -630,6 +630,52 @@ function splitLocaleFromPath(path, siteLocales) {
630
630
  }
631
631
  return { locale: siteLocales.defaultLocale, path };
632
632
  }
633
+
634
+ // src/data/localize-href.ts
635
+ var PROTOCOL_OR_RELATIVE = /^([a-z][a-z0-9+.-]*:|\/\/)/i;
636
+ function isExternalHref(href) {
637
+ const value = href.trim();
638
+ if (!value) return true;
639
+ if (value.startsWith("#")) return true;
640
+ return PROTOCOL_OR_RELATIVE.test(value);
641
+ }
642
+ function stripLeadingLocale(path, locale) {
643
+ const segments = path.split("/");
644
+ const first = segments[1];
645
+ if (first && first !== locale.default && locale.enabled.includes(first)) {
646
+ segments.splice(1, 1);
647
+ const rest = segments.join("/");
648
+ return rest === "" ? "/" : rest;
649
+ }
650
+ return path;
651
+ }
652
+ function addLocalePrefix(path, target, locale) {
653
+ if (target === locale.default) return path;
654
+ if (path === "/") return `/${target}`;
655
+ return `/${target}${path}`;
656
+ }
657
+ function localizeHref(href, locale) {
658
+ const value = href.trim();
659
+ if (isExternalHref(value)) return href;
660
+ const boundary = value.search(/[?#]/);
661
+ const path = boundary === -1 ? value : value.slice(0, boundary);
662
+ const suffix = boundary === -1 ? "" : value.slice(boundary);
663
+ if (!path.startsWith("/")) return href;
664
+ const bare = stripLeadingLocale(path, locale);
665
+ return `${addLocalePrefix(bare, locale.current, locale)}${suffix}`;
666
+ }
667
+ function buildLocaleSwitchHref(target, pathname, locale) {
668
+ const path = pathname && pathname.startsWith("/") ? pathname : "/";
669
+ const bare = stripLeadingLocale(path, locale);
670
+ return addLocalePrefix(bare, target, locale);
671
+ }
672
+ var ANCHOR_HREF = /(<a\b(?:"[^"]*"|'[^']*'|[^>])*?\shref=)(["'])(.*?)\2/gi;
673
+ function localizeHtmlLinks(html, locale) {
674
+ return html.replace(
675
+ ANCHOR_HREF,
676
+ (_match, prefix, quote, url) => `${prefix}${quote}${localizeHref(url, locale)}${quote}`
677
+ );
678
+ }
633
679
  function CmssyBlock({
634
680
  block,
635
681
  locale,
@@ -670,6 +716,7 @@ exports.blocksToMeta = blocksToMeta;
670
716
  exports.blocksToSchemas = blocksToSchemas;
671
717
  exports.buildBlockContext = buildBlockContext;
672
718
  exports.buildBlockMap = buildBlockMap;
719
+ exports.buildLocaleSwitchHref = buildLocaleSwitchHref;
673
720
  exports.collectFormIds = collectFormIds;
674
721
  exports.createCmssyClient = createCmssyClient;
675
722
  exports.defineBlock = defineBlock;
@@ -679,6 +726,8 @@ exports.fields = fields;
679
726
  exports.getBlockContentForLanguage = getBlockContentForLanguage;
680
727
  exports.graphqlRequest = graphqlRequest;
681
728
  exports.isProtocolCompatible = isProtocolCompatible;
729
+ exports.localizeHref = localizeHref;
730
+ exports.localizeHtmlLinks = localizeHtmlLinks;
682
731
  exports.normalizeOrigin = normalizeOrigin;
683
732
  exports.normalizeSlug = normalizeSlug;
684
733
  exports.parseEditorMessage = parseEditorMessage;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FieldDefinition, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, E as EditorToAppMessage, A as AppToEditorMessage, m as FetchLike, n as CmssyClientConfig, R as RawBlock, o as BlockMap, p as CmssyBlockContext } from './commerce-queries-BYx7uUnE.cjs';
2
- export { a as BlockMeta, q as BlockRect, B as BlockSchema, r as BoundsMessage, s as ClickMessage, t as CmssyBranding, e as CmssyCart, h as CmssyCartDiscount, i as CmssyCartItem, j as CmssyCartItemSnapshot, u as CmssyFormField, v as CmssyFormSettings, w as CmssyFormSubmitResponse, x as CmssyLocaleContext, y as CmssyModelDefinition, z as CmssyModelRecord, f as CmssyOrder, g as CmssyProduct, l as CmssyProductVariant, D as CmssyRecordList, G as CmssySiteConfig, H as FORM_QUERY, I as FetchLikeResponse, J as FetchPageOptions, K as FieldType, M as MODEL_DEFINITIONS_QUERY, L as MODEL_RECORDS_QUERY, P as PROTOCOL_VERSION, N as ParentReadyMessage, O as PatchMessage, Q as RawLayoutBlock, S as ReadyMessage, T as SITE_CONFIG_QUERY, U as SUBMIT_FORM_MUTATION, V as SelectMessage, W as SubmitFormInput, X as blocksToMeta, Y as blocksToSchemas, Z as buildBlockContext, _ as buildBlockMap, $ as defineBlock, a0 as fetchLayouts, a1 as fetchPage, a2 as isProtocolCompatible, a3 as normalizeSlug } from './commerce-queries-BYx7uUnE.cjs';
1
+ import { F as FieldDefinition, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, E as EditorToAppMessage, A as AppToEditorMessage, n as FetchLike, o as CmssyClientConfig, R as RawBlock, e as CmssyLocaleContext, p as BlockMap, q as CmssyBlockContext } from './commerce-queries-CqCdTD31.cjs';
2
+ export { a as BlockMeta, r as BlockRect, B as BlockSchema, s as BoundsMessage, t as ClickMessage, u as CmssyBranding, f as CmssyCart, i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, v as CmssyFormField, w as CmssyFormSettings, x as CmssyFormSubmitResponse, y as CmssyModelDefinition, z as CmssyModelRecord, g as CmssyOrder, h as CmssyProduct, m as CmssyProductVariant, D as CmssyRecordList, G as CmssySiteConfig, H as FORM_QUERY, I as FetchLikeResponse, J as FetchPageOptions, K as FieldType, M as MODEL_DEFINITIONS_QUERY, L as MODEL_RECORDS_QUERY, P as PROTOCOL_VERSION, N as ParentReadyMessage, O as PatchMessage, Q as RawLayoutBlock, S as ReadyMessage, T as SITE_CONFIG_QUERY, U as SUBMIT_FORM_MUTATION, V as SelectMessage, W as SubmitFormInput, X as blocksToMeta, Y as blocksToSchemas, Z as buildBlockContext, _ as buildBlockMap, $ as defineBlock, a0 as fetchLayouts, a1 as fetchPage, a2 as isProtocolCompatible, a3 as normalizeSlug } from './commerce-queries-CqCdTD31.cjs';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import 'react';
5
5
 
@@ -91,6 +91,23 @@ declare function splitLocaleFromPath(path: string[] | undefined, siteLocales: Cm
91
91
  path: string[] | undefined;
92
92
  };
93
93
 
94
+ /**
95
+ * Rewrites an internal href to carry the active locale as a path prefix.
96
+ * External hrefs, fragments and relative paths are returned untouched. Already
97
+ * prefixed hrefs are normalized so the prefix never doubles.
98
+ */
99
+ declare function localizeHref(href: string, locale: CmssyLocaleContext): string;
100
+ /**
101
+ * Builds the href that switches the current `pathname` to `target` locale,
102
+ * preserving the rest of the path. Used by a language switcher.
103
+ */
104
+ declare function buildLocaleSwitchHref(target: string, pathname: string, locale: CmssyLocaleContext): string;
105
+ /**
106
+ * Rewrites every `<a href>` inside an HTML string with {@link localizeHref}.
107
+ * For rich-text content stored in CMS blocks where links are raw markup.
108
+ */
109
+ declare function localizeHtmlLinks(html: string, locale: CmssyLocaleContext): string;
110
+
94
111
  interface CmssyBlockProps {
95
112
  block: RawBlock;
96
113
  locale: string;
@@ -108,4 +125,4 @@ interface UnknownBlockProps {
108
125
  }
109
126
  declare function UnknownBlock({ type }: UnknownBlockProps): react_jsx_runtime.JSX.Element;
110
127
 
111
- export { AppToEditorMessage, BlockDefinition, BlockMap, CmssyBlock, CmssyBlockContext, type CmssyBlockProps, type CmssyClient, CmssyClientConfig, CmssyFormDefinition, CmssyLayoutGroup, CmssyPageData, CmssyServerLayout, type CmssyServerLayoutProps, CmssyServerPage, type CmssyServerPageProps, type CmssySiteLocales, EditorToAppMessage, FetchLike, type FieldControl, FieldDefinition, type GraphqlRequestOptions, type PostTarget, type QueryScopedOptions, RawBlock, UnknownBlock, type UnknownBlockProps, collectFormIds, createCmssyClient, fields, getBlockContentForLanguage, graphqlRequest, normalizeOrigin, parseEditorMessage, postToEditor, resolveForms, resolveSiteLocales, resolveWorkspaceId, splitLocaleFromPath };
128
+ export { AppToEditorMessage, BlockDefinition, BlockMap, CmssyBlock, CmssyBlockContext, type CmssyBlockProps, type CmssyClient, CmssyClientConfig, CmssyFormDefinition, CmssyLayoutGroup, CmssyLocaleContext, CmssyPageData, CmssyServerLayout, type CmssyServerLayoutProps, CmssyServerPage, type CmssyServerPageProps, type CmssySiteLocales, EditorToAppMessage, FetchLike, type FieldControl, FieldDefinition, type GraphqlRequestOptions, type PostTarget, type QueryScopedOptions, RawBlock, UnknownBlock, type UnknownBlockProps, buildLocaleSwitchHref, collectFormIds, createCmssyClient, fields, getBlockContentForLanguage, graphqlRequest, localizeHref, localizeHtmlLinks, normalizeOrigin, parseEditorMessage, postToEditor, resolveForms, resolveSiteLocales, resolveWorkspaceId, splitLocaleFromPath };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FieldDefinition, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, E as EditorToAppMessage, A as AppToEditorMessage, m as FetchLike, n as CmssyClientConfig, R as RawBlock, o as BlockMap, p as CmssyBlockContext } from './commerce-queries-BYx7uUnE.js';
2
- export { a as BlockMeta, q as BlockRect, B as BlockSchema, r as BoundsMessage, s as ClickMessage, t as CmssyBranding, e as CmssyCart, h as CmssyCartDiscount, i as CmssyCartItem, j as CmssyCartItemSnapshot, u as CmssyFormField, v as CmssyFormSettings, w as CmssyFormSubmitResponse, x as CmssyLocaleContext, y as CmssyModelDefinition, z as CmssyModelRecord, f as CmssyOrder, g as CmssyProduct, l as CmssyProductVariant, D as CmssyRecordList, G as CmssySiteConfig, H as FORM_QUERY, I as FetchLikeResponse, J as FetchPageOptions, K as FieldType, M as MODEL_DEFINITIONS_QUERY, L as MODEL_RECORDS_QUERY, P as PROTOCOL_VERSION, N as ParentReadyMessage, O as PatchMessage, Q as RawLayoutBlock, S as ReadyMessage, T as SITE_CONFIG_QUERY, U as SUBMIT_FORM_MUTATION, V as SelectMessage, W as SubmitFormInput, X as blocksToMeta, Y as blocksToSchemas, Z as buildBlockContext, _ as buildBlockMap, $ as defineBlock, a0 as fetchLayouts, a1 as fetchPage, a2 as isProtocolCompatible, a3 as normalizeSlug } from './commerce-queries-BYx7uUnE.js';
1
+ import { F as FieldDefinition, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, E as EditorToAppMessage, A as AppToEditorMessage, n as FetchLike, o as CmssyClientConfig, R as RawBlock, e as CmssyLocaleContext, p as BlockMap, q as CmssyBlockContext } from './commerce-queries-CqCdTD31.js';
2
+ export { a as BlockMeta, r as BlockRect, B as BlockSchema, s as BoundsMessage, t as ClickMessage, u as CmssyBranding, f as CmssyCart, i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, v as CmssyFormField, w as CmssyFormSettings, x as CmssyFormSubmitResponse, y as CmssyModelDefinition, z as CmssyModelRecord, g as CmssyOrder, h as CmssyProduct, m as CmssyProductVariant, D as CmssyRecordList, G as CmssySiteConfig, H as FORM_QUERY, I as FetchLikeResponse, J as FetchPageOptions, K as FieldType, M as MODEL_DEFINITIONS_QUERY, L as MODEL_RECORDS_QUERY, P as PROTOCOL_VERSION, N as ParentReadyMessage, O as PatchMessage, Q as RawLayoutBlock, S as ReadyMessage, T as SITE_CONFIG_QUERY, U as SUBMIT_FORM_MUTATION, V as SelectMessage, W as SubmitFormInput, X as blocksToMeta, Y as blocksToSchemas, Z as buildBlockContext, _ as buildBlockMap, $ as defineBlock, a0 as fetchLayouts, a1 as fetchPage, a2 as isProtocolCompatible, a3 as normalizeSlug } from './commerce-queries-CqCdTD31.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import 'react';
5
5
 
@@ -91,6 +91,23 @@ declare function splitLocaleFromPath(path: string[] | undefined, siteLocales: Cm
91
91
  path: string[] | undefined;
92
92
  };
93
93
 
94
+ /**
95
+ * Rewrites an internal href to carry the active locale as a path prefix.
96
+ * External hrefs, fragments and relative paths are returned untouched. Already
97
+ * prefixed hrefs are normalized so the prefix never doubles.
98
+ */
99
+ declare function localizeHref(href: string, locale: CmssyLocaleContext): string;
100
+ /**
101
+ * Builds the href that switches the current `pathname` to `target` locale,
102
+ * preserving the rest of the path. Used by a language switcher.
103
+ */
104
+ declare function buildLocaleSwitchHref(target: string, pathname: string, locale: CmssyLocaleContext): string;
105
+ /**
106
+ * Rewrites every `<a href>` inside an HTML string with {@link localizeHref}.
107
+ * For rich-text content stored in CMS blocks where links are raw markup.
108
+ */
109
+ declare function localizeHtmlLinks(html: string, locale: CmssyLocaleContext): string;
110
+
94
111
  interface CmssyBlockProps {
95
112
  block: RawBlock;
96
113
  locale: string;
@@ -108,4 +125,4 @@ interface UnknownBlockProps {
108
125
  }
109
126
  declare function UnknownBlock({ type }: UnknownBlockProps): react_jsx_runtime.JSX.Element;
110
127
 
111
- export { AppToEditorMessage, BlockDefinition, BlockMap, CmssyBlock, CmssyBlockContext, type CmssyBlockProps, type CmssyClient, CmssyClientConfig, CmssyFormDefinition, CmssyLayoutGroup, CmssyPageData, CmssyServerLayout, type CmssyServerLayoutProps, CmssyServerPage, type CmssyServerPageProps, type CmssySiteLocales, EditorToAppMessage, FetchLike, type FieldControl, FieldDefinition, type GraphqlRequestOptions, type PostTarget, type QueryScopedOptions, RawBlock, UnknownBlock, type UnknownBlockProps, collectFormIds, createCmssyClient, fields, getBlockContentForLanguage, graphqlRequest, normalizeOrigin, parseEditorMessage, postToEditor, resolveForms, resolveSiteLocales, resolveWorkspaceId, splitLocaleFromPath };
128
+ export { AppToEditorMessage, BlockDefinition, BlockMap, CmssyBlock, CmssyBlockContext, type CmssyBlockProps, type CmssyClient, CmssyClientConfig, CmssyFormDefinition, CmssyLayoutGroup, CmssyLocaleContext, CmssyPageData, CmssyServerLayout, type CmssyServerLayoutProps, CmssyServerPage, type CmssyServerPageProps, type CmssySiteLocales, EditorToAppMessage, FetchLike, type FieldControl, FieldDefinition, type GraphqlRequestOptions, type PostTarget, type QueryScopedOptions, RawBlock, UnknownBlock, type UnknownBlockProps, buildLocaleSwitchHref, collectFormIds, createCmssyClient, fields, getBlockContentForLanguage, graphqlRequest, localizeHref, localizeHtmlLinks, normalizeOrigin, parseEditorMessage, postToEditor, resolveForms, resolveSiteLocales, resolveWorkspaceId, splitLocaleFromPath };
package/dist/index.js CHANGED
@@ -628,6 +628,52 @@ function splitLocaleFromPath(path, siteLocales) {
628
628
  }
629
629
  return { locale: siteLocales.defaultLocale, path };
630
630
  }
631
+
632
+ // src/data/localize-href.ts
633
+ var PROTOCOL_OR_RELATIVE = /^([a-z][a-z0-9+.-]*:|\/\/)/i;
634
+ function isExternalHref(href) {
635
+ const value = href.trim();
636
+ if (!value) return true;
637
+ if (value.startsWith("#")) return true;
638
+ return PROTOCOL_OR_RELATIVE.test(value);
639
+ }
640
+ function stripLeadingLocale(path, locale) {
641
+ const segments = path.split("/");
642
+ const first = segments[1];
643
+ if (first && first !== locale.default && locale.enabled.includes(first)) {
644
+ segments.splice(1, 1);
645
+ const rest = segments.join("/");
646
+ return rest === "" ? "/" : rest;
647
+ }
648
+ return path;
649
+ }
650
+ function addLocalePrefix(path, target, locale) {
651
+ if (target === locale.default) return path;
652
+ if (path === "/") return `/${target}`;
653
+ return `/${target}${path}`;
654
+ }
655
+ function localizeHref(href, locale) {
656
+ const value = href.trim();
657
+ if (isExternalHref(value)) return href;
658
+ const boundary = value.search(/[?#]/);
659
+ const path = boundary === -1 ? value : value.slice(0, boundary);
660
+ const suffix = boundary === -1 ? "" : value.slice(boundary);
661
+ if (!path.startsWith("/")) return href;
662
+ const bare = stripLeadingLocale(path, locale);
663
+ return `${addLocalePrefix(bare, locale.current, locale)}${suffix}`;
664
+ }
665
+ function buildLocaleSwitchHref(target, pathname, locale) {
666
+ const path = pathname && pathname.startsWith("/") ? pathname : "/";
667
+ const bare = stripLeadingLocale(path, locale);
668
+ return addLocalePrefix(bare, target, locale);
669
+ }
670
+ var ANCHOR_HREF = /(<a\b(?:"[^"]*"|'[^']*'|[^>])*?\shref=)(["'])(.*?)\2/gi;
671
+ function localizeHtmlLinks(html, locale) {
672
+ return html.replace(
673
+ ANCHOR_HREF,
674
+ (_match, prefix, quote, url) => `${prefix}${quote}${localizeHref(url, locale)}${quote}`
675
+ );
676
+ }
631
677
  function CmssyBlock({
632
678
  block,
633
679
  locale,
@@ -654,4 +700,4 @@ function CmssyBlock({
654
700
  );
655
701
  }
656
702
 
657
- export { CmssyBlock, CmssyServerLayout, CmssyServerPage, FORM_QUERY, MODEL_DEFINITIONS_QUERY, MODEL_RECORDS_QUERY, PROTOCOL_VERSION, SITE_CONFIG_QUERY, SUBMIT_FORM_MUTATION, UnknownBlock, blocksToMeta, blocksToSchemas, buildBlockContext, buildBlockMap, collectFormIds, createCmssyClient, defineBlock, fetchLayouts, fetchPage, fields, getBlockContentForLanguage, graphqlRequest, isProtocolCompatible, normalizeOrigin, normalizeSlug, parseEditorMessage, postToEditor, resolveForms, resolveSiteLocales, resolveWorkspaceId, splitLocaleFromPath };
703
+ export { CmssyBlock, CmssyServerLayout, CmssyServerPage, FORM_QUERY, MODEL_DEFINITIONS_QUERY, MODEL_RECORDS_QUERY, PROTOCOL_VERSION, SITE_CONFIG_QUERY, SUBMIT_FORM_MUTATION, UnknownBlock, blocksToMeta, blocksToSchemas, buildBlockContext, buildBlockMap, buildLocaleSwitchHref, collectFormIds, createCmssyClient, defineBlock, fetchLayouts, fetchPage, fields, getBlockContentForLanguage, graphqlRequest, isProtocolCompatible, localizeHref, localizeHtmlLinks, normalizeOrigin, normalizeSlug, parseEditorMessage, postToEditor, resolveForms, resolveSiteLocales, resolveWorkspaceId, splitLocaleFromPath };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmssy/react",
3
- "version": "0.2.5",
3
+ "version": "0.3.0",
4
4
  "description": "React blocks, renderers, data client and editor bridge for cmssy headless sites",
5
5
  "keywords": [
6
6
  "cmssy",