@elytracms/next 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 finaldream
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ export { ContentAssetView, ContentClient, ContentClientProvider, ContentDocumentView, ContentQuery, RenderErrorBoundary, RenderErrorFallback, createFixtureContentClient, useContentClient } from '@elytracms/runtime-renderer/client';
package/dist/client.js ADDED
@@ -0,0 +1,47 @@
1
+ 'use client'
2
+ import { createContext, createElement, useContext, Component } from 'react';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ var ContentClientContext = createContext(null);
6
+ function ContentClientProvider({ client, children }) {
7
+ return createElement(ContentClientContext.Provider, { value: client }, children);
8
+ }
9
+ function useContentClient() {
10
+ return useContext(ContentClientContext);
11
+ }
12
+ function createFixtureContentClient(fixtures) {
13
+ const docs = fixtures.documents ?? [];
14
+ const assets = new Map((fixtures.assets ?? []).map((a) => [a.id, a]));
15
+ return {
16
+ getDocument: (collection, id) => docs.find((d) => d.collection === collection && d.id === id),
17
+ listDocuments: (query) => {
18
+ const matched = docs.filter((d) => d.collection === query.collection);
19
+ return query.limit === void 0 ? matched : matched.slice(0, query.limit);
20
+ },
21
+ resolveAsset: (id) => assets.get(id)
22
+ };
23
+ }
24
+ function RenderErrorFallback(props) {
25
+ return jsx("div", { "data-ec-fallback": "render-error", "data-ec-node-id": props.nodeId, children: props.message ? `Render error in node ${props.nodeId}: ${props.message}` : `Render error in node ${props.nodeId}` });
26
+ }
27
+ var RenderErrorBoundary = class extends Component {
28
+ constructor(props) {
29
+ super(props);
30
+ this.state = { error: null };
31
+ }
32
+ static getDerivedStateFromError(error) {
33
+ return { error };
34
+ }
35
+ componentDidCatch(_error, _info) {
36
+ }
37
+ render() {
38
+ if (this.state.error) {
39
+ return jsx(RenderErrorFallback, { nodeId: this.props.nodeId, message: this.state.error.message });
40
+ }
41
+ return this.props.children;
42
+ }
43
+ };
44
+
45
+ export { ContentClientProvider, RenderErrorBoundary, RenderErrorFallback, createFixtureContentClient, useContentClient };
46
+ //# sourceMappingURL=client.js.map
47
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../runtime-renderer/src/content-client.tsx","../../runtime-renderer/src/fallback.tsx"],"names":["_jsx"],"mappings":";;;AA8CA,IAAM,oBAAA,GAAuB,cAAoC,IAAI,CAAA;AAO/D,SAAU,qBAAA,CAAsB,EACpC,MAAA,EACA,QAAA,EAAQ,EAIT;AACC,EAAA,OAAO,cAAc,oBAAA,CAAqB,QAAA,EAAU,EAAE,KAAA,EAAO,MAAA,IAAU,QAAQ,CAAA;AACjF;AAOM,SAAU,gBAAA,GAAgB;AAC9B,EAAA,OAAO,WAAW,oBAAoB,CAAA;AACxC;AAOM,SAAU,2BAA2B,QAAA,EAG1C;AACC,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,SAAA,IAAa,EAAA;AACnC,EAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAA,CAAK,QAAA,CAAS,UAAU,EAAA,EAAI,GAAA,CAAI,CAAC,MAAM,CAAC,CAAA,CAAE,EAAA,EAAI,CAAC,CAAC,CAAC,CAAA;AACpE,EAAA,OAAO;AACL,IAAA,WAAA,EAAa,CAAC,UAAA,EAAY,EAAA,KACxB,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,UAAA,KAAe,UAAA,IAAc,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA;AAC7D,IAAA,aAAA,EAAe,CAAC,KAAA,KAAS;AACvB,MAAA,MAAM,OAAA,GAAU,KAAK,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,UAAA,KAAe,MAAM,UAAU,CAAA;AACpE,MAAA,OAAO,KAAA,CAAM,UAAU,MAAA,GAAY,OAAA,GAAU,QAAQ,KAAA,CAAM,CAAA,EAAG,MAAM,KAAK,CAAA;AAC3E,IAAA,CAAA;AACA,IAAA,YAAA,EAAc,CAAC,EAAA,KAAO,MAAA,CAAO,GAAA,CAAI,EAAE;;AAEvC;AC1DM,SAAU,oBAAoB,KAAA,EAA2C;AAC7E,EAAA,OACEA,GAAA,CAAA,OAAA,EAAA,kBAAA,EAAsB,gBAAc,iBAAA,EAAkB,KAAA,CAAM,MAAA,EAAM,QAAA,EAC/D,KAAA,CAAM,OAAA,GACH,wBAAwB,KAAA,CAAM,MAAM,KAAK,KAAA,CAAM,OAAO,KACtD,CAAA,qBAAA,EAAwB,KAAA,CAAM,MAAM,CAAA,CAAA,EAAE,CAAA;AAGhD;AAgBM,IAAO,mBAAA,GAAP,cAAmC,SAAA,CAAiD;AACxF,EAAA,WAAA,CAAY,KAAA,EAAyB;AACnC,IAAA,KAAA,CAAM,KAAK,CAAA;AACX,IAAA,IAAA,CAAK,KAAA,GAAQ,EAAE,KAAA,EAAO,IAAA,EAAI;AAC5B,EAAA;AAEA,EAAA,OAAO,yBAAyB,KAAA,EAAY;AAC1C,IAAA,OAAO,EAAE,KAAA,EAAK;AAChB,EAAA;AAES,EAAA,iBAAA,CAAkB,QAAe,KAAA,EAAgB;AAG1D,EAAA;EAES,MAAA,GAAM;AACb,IAAA,IAAI,IAAA,CAAK,MAAM,KAAA,EAAO;AACpB,MAAA,OAAOA,GAAA,CAAC,mBAAA,EAAmB,EAAC,MAAA,EAAQ,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,OAAA,EAAO,CAAA;AAC1F,IAAA;AACA,IAAA,OAAO,KAAK,KAAA,CAAM,QAAA;AACpB,EAAA","file":"client.js","sourcesContent":["'use client'\n\nimport { createContext, createElement, useContext } from 'react'\nimport type { ReactNode } from 'react'\n\n/**\n * Read-only content access for self-fetching components (EC-191). With editor\n * bindings gone (EC-190), dynamic data lives INSIDE dev components: a component\n * reads what it needs from the injected client and renders it. The host provides a\n * live client (Convex-backed), the studio a read client, tests a fixture-backed\n * deterministic one — so the SAME component renders real data on the canvas, at\n * delivery, and in tests (the AGENTS.md determinism rule).\n *\n * The client is **synchronous**: it reads already-loaded content (the host fetches\n * for delivery, the studio pre-loads for preview, the test holds fixtures), which\n * keeps render deterministic and Suspense-free. A component may ALSO fetch arbitrary\n * external content through its own async hooks — the client is one source, not the\n * only one.\n */\nexport interface ContentDocumentView {\n collection: string\n id: string\n values: Record<string, unknown>\n}\n\n/** A resolved asset (EC-191) — id plus delivery-shape url/alt when known. */\nexport interface ContentAssetView {\n id: string\n url?: string\n alt?: string\n}\n\n/** A minimal list query (EC-191). Kept deliberately small for v1. */\nexport interface ContentQuery {\n collection: string\n /** Cap the number of returned documents. */\n limit?: number\n}\n\n/** The read-content contract injected into the render context (EC-191). */\nexport interface ContentClient {\n getDocument(collection: string, id: string): ContentDocumentView | undefined\n listDocuments(query: ContentQuery): ContentDocumentView[]\n resolveAsset(id: string): ContentAssetView | undefined\n}\n\nconst ContentClientContext = createContext<ContentClient | null>(null)\n\n/**\n * Provide a `ContentClient` to the rendered subtree. The renderer wraps its public\n * composite entry points (page/composition) in this when `ctx.content` is set; a\n * host rendering nodes directly can wrap manually.\n */\nexport function ContentClientProvider({\n client,\n children,\n}: {\n client: ContentClient\n children: ReactNode\n}): ReactNode {\n return createElement(ContentClientContext.Provider, { value: client }, children)\n}\n\n/**\n * Read the injected `ContentClient` inside a component implementation (EC-191).\n * Returns `null` when none is provided (e.g. a pure-static render) — a self-fetching\n * component must degrade visibly, never crash, when content access is absent.\n */\nexport function useContentClient(): ContentClient | null {\n return useContext(ContentClientContext)\n}\n\n/**\n * A deterministic, in-memory `ContentClient` over fixed documents + assets (EC-191).\n * The studio preview and tests use it so a self-fetching component renders the same\n * content every time. `limit` is the only query knob in v1.\n */\nexport function createFixtureContentClient(fixtures: {\n documents?: readonly ContentDocumentView[]\n assets?: readonly ContentAssetView[]\n}): ContentClient {\n const docs = fixtures.documents ?? []\n const assets = new Map((fixtures.assets ?? []).map((a) => [a.id, a]))\n return {\n getDocument: (collection, id) =>\n docs.find((d) => d.collection === collection && d.id === id),\n listDocuments: (query) => {\n const matched = docs.filter((d) => d.collection === query.collection)\n return query.limit === undefined ? matched : matched.slice(0, query.limit)\n },\n resolveAsset: (id) => assets.get(id),\n }\n}\n","'use client'\n\nimport { Component } from 'react'\nimport type { ErrorInfo, ReactNode } from 'react'\n\n/**\n * Visible fallback for a node whose component has no manifest or no implementation.\n * Renders instead of throwing so a single bad reference never blanks the page (brief §4.11).\n */\nexport function MissingComponentFallback(props: {\n nodeId: string\n componentId: string\n}): ReactNode {\n return (\n <div\n data-ec-fallback=\"missing-component\"\n data-ec-node-id={props.nodeId}\n data-ec-component-id={props.componentId}\n >\n {`Missing component \"${props.componentId}\" (node ${props.nodeId})`}\n </div>\n )\n}\n\n/** Visible placeholder rendered in the position of a required slot that has no children. */\nexport function MissingSlotPlaceholder(props: { nodeId: string; slot: string }): ReactNode {\n return (\n <div data-ec-fallback=\"missing-slot\" data-ec-node-id={props.nodeId} data-ec-slot={props.slot}>\n {`Missing required slot \"${props.slot}\" (node ${props.nodeId})`}\n </div>\n )\n}\n\n/** Visible fallback for a node that threw while resolving props/bindings or while rendering. */\nexport function RenderErrorFallback(props: { nodeId: string; message?: string }): ReactNode {\n return (\n <div data-ec-fallback=\"render-error\" data-ec-node-id={props.nodeId}>\n {props.message\n ? `Render error in node ${props.nodeId}: ${props.message}`\n : `Render error in node ${props.nodeId}`}\n </div>\n )\n}\n\ninterface ErrorBoundaryProps {\n nodeId: string\n children: ReactNode\n}\n\ninterface ErrorBoundaryState {\n error: Error | null\n}\n\n/**\n * Client-side error boundary: when a descendant component throws during render, this swaps\n * in a visible fallback rather than unmounting the whole tree. Server rendering cannot use\n * boundaries to recover, so the renderer additionally wraps resolution in try/catch.\n */\nexport class RenderErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props)\n this.state = { error: null }\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { error }\n }\n\n override componentDidCatch(_error: Error, _info: ErrorInfo): void {\n // Intentionally swallowed: the fallback is the user-visible signal. Hosts may add\n // their own logging by wrapping this boundary.\n }\n\n override render(): ReactNode {\n if (this.state.error) {\n return <RenderErrorFallback nodeId={this.props.nodeId} message={this.state.error.message} />\n }\n return this.props.children\n }\n}\n"]}