@limitless-angular/sanity
Version:
A powerful Angular library for Sanity.io integration, featuring Portable Text rendering and optimized image loading.
1,237 lines (1,206 loc) • 47.9 kB
JavaScript
import * as i0 from '@angular/core';
import { viewChild, Component, ChangeDetectionStrategy, ViewEncapsulation, InjectionToken, inject, input, ViewContainerRef, Injector, computed, forwardRef, Directive } from '@angular/core';
import { NgTemplateOutlet, NgComponentOutlet } from '@angular/common';
import { buildMarksTree, spanToPlainText, nestLists, LIST_NEST_MODE_HTML, isPortableTextToolkitList, isPortableTextListItemBlock, isPortableTextBlock, isPortableTextToolkitSpan, isPortableTextToolkitTextNode } from '@portabletext/toolkit';
export { toPlainText } from '@portabletext/toolkit';
function serializeBlock(options) {
const { node, isInline } = options;
const tree = buildMarksTree(node);
const children = tree.map((child, i) => ({
...child,
// TODO: check this _key generation
// eslint-disable-next-line @typescript-eslint/no-explicit-any
_key: child._key ?? `block-${i}`,
}));
return {
_key: node._key,
children,
isInline,
node,
};
}
function trackBy(key, index, prefix = 'node') {
return key ?? `${prefix}-${index}`;
}
class BlockComponent {
constructor() {
this.template = viewChild.required('blockTmpl');
this.serializeBlock = serializeBlock;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: BlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: BlockComponent, isStandalone: true, selector: "lib-block", viewQueries: [{ propertyName: "template", first: true, predicate: ["blockTmpl"], descendants: true, isSignal: true }], ngImport: i0, template: `
<ng-template
#blockTmpl
let-node
let-isInline="isInline"
let-components="components"
let-renderNode="renderNode"
>
<ng-template #children>
<ng-container
*ngTemplateOutlet="
blockChildren;
context: { node, isInline, components, renderNode }
"
/>
</ng-template>
@if (components.block?.[node.style ?? 'normal']) {
<ng-container
*ngComponentOutlet="
components.block?.[node.style ?? 'normal'];
inputs: {
childrenData: {
template: blockChildren,
context: { node, isInline, components, renderNode },
},
value: node,
isInline,
}
"
/>
} @else {
@switch (node.style ?? 'normal') {
@case ('normal') {
<p>
<ng-container *ngTemplateOutlet="children" />
</p>
}
@case ('h1') {
<h1>
<ng-container *ngTemplateOutlet="children" />
</h1>
}
@case ('h2') {
<h2>
<ng-container *ngTemplateOutlet="children" />
</h2>
}
@case ('h3') {
<h3>
<ng-container *ngTemplateOutlet="children" />
</h3>
}
@case ('h4') {
<h4>
<ng-container *ngTemplateOutlet="children" />
</h4>
}
@case ('h5') {
<h5>
<ng-container *ngTemplateOutlet="children" />
</h5>
}
@case ('h6') {
<h6>
<ng-container *ngTemplateOutlet="children" />
</h6>
}
@case ('blockquote') {
<blockquote>
<ng-container *ngTemplateOutlet="children" />
</blockquote>
}
@default {
<!-- TODO: remove class when warning msg be implemented -->
<p [class]="'unknown__pt__block__' + node.style">
<ng-container *ngTemplateOutlet="children" />
</p>
}
}
}
</ng-template>
<ng-template
#blockChildren
let-node="node"
let-isInline="isInline"
let-components="components"
let-renderNode="renderNode"
>
@for (
child of serializeBlock({ node, isInline: false }).children;
track child._key;
let childIndex = $index
) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: {
$implicit: child,
index: childIndex,
isInline: true,
components,
}
"
/>
}
</ng-template>
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: BlockComponent, decorators: [{
type: Component,
args: [{
selector: 'lib-block',
imports: [NgTemplateOutlet, NgComponentOutlet],
template: `
<ng-template
#blockTmpl
let-node
let-isInline="isInline"
let-components="components"
let-renderNode="renderNode"
>
<ng-template #children>
<ng-container
*ngTemplateOutlet="
blockChildren;
context: { node, isInline, components, renderNode }
"
/>
</ng-template>
@if (components.block?.[node.style ?? 'normal']) {
<ng-container
*ngComponentOutlet="
components.block?.[node.style ?? 'normal'];
inputs: {
childrenData: {
template: blockChildren,
context: { node, isInline, components, renderNode },
},
value: node,
isInline,
}
"
/>
} @else {
@switch (node.style ?? 'normal') {
@case ('normal') {
<p>
<ng-container *ngTemplateOutlet="children" />
</p>
}
@case ('h1') {
<h1>
<ng-container *ngTemplateOutlet="children" />
</h1>
}
@case ('h2') {
<h2>
<ng-container *ngTemplateOutlet="children" />
</h2>
}
@case ('h3') {
<h3>
<ng-container *ngTemplateOutlet="children" />
</h3>
}
@case ('h4') {
<h4>
<ng-container *ngTemplateOutlet="children" />
</h4>
}
@case ('h5') {
<h5>
<ng-container *ngTemplateOutlet="children" />
</h5>
}
@case ('h6') {
<h6>
<ng-container *ngTemplateOutlet="children" />
</h6>
}
@case ('blockquote') {
<blockquote>
<ng-container *ngTemplateOutlet="children" />
</blockquote>
}
@default {
<!-- TODO: remove class when warning msg be implemented -->
<p [class]="'unknown__pt__block__' + node.style">
<ng-container *ngTemplateOutlet="children" />
</p>
}
}
}
</ng-template>
<ng-template
#blockChildren
let-node="node"
let-isInline="isInline"
let-components="components"
let-renderNode="renderNode"
>
@for (
child of serializeBlock({ node, isInline: false }).children;
track child._key;
let childIndex = $index
) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: {
$implicit: child,
index: childIndex,
isInline: true,
components,
}
"
/>
}
</ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
}]
}] });
class TextComponent {
constructor() {
this.template = viewChild.required('textTmpl');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: TextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: TextComponent, isStandalone: true, selector: "lib-text", viewQueries: [{ propertyName: "template", first: true, predicate: ["textTmpl"], descendants: true, isSignal: true }], ngImport: i0, template: `<ng-template #textTmpl let-node let-components="components">
@if (node.text === '\\n') {
@if (components.hardBreak === undefined) {<br />}
@else if (components.hardBreak === false) {{{ '\\n' }}}
@else {<ng-container *ngComponentOutlet="components.hardBreak" />}
} @else {{{ node.text }}}
</ng-template>`, isInline: true, dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: TextComponent, decorators: [{
type: Component,
args: [{
selector: 'lib-text',
// prettier-ignore
template: `<ng-template #textTmpl let-node let-components="components">
@if (node.text === '\\n') {
@if (components.hardBreak === undefined) {<br />}
@else if (components.hardBreak === false) {{{ '\\n' }}}
@else {<ng-container *ngComponentOutlet="components.hardBreak" />}
} @else {{{ node.text }}}
</ng-template>`,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
imports: [NgComponentOutlet],
}]
}] });
const MISSING_COMPONENT_HANDLER = new InjectionToken('Missing Component Handler');
const getTemplate = (type, prop) => `[@limitless-angular/sanity/portabletext] Unknown ${type}, specify a component for it in the \`components.${prop}\` prop`;
const unknownTypeWarning = (typeName) => getTemplate(`block type "${typeName}"`, 'types');
const unknownMarkWarning = (markType) => getTemplate(`mark type "${markType}"`, 'marks');
const unknownBlockStyleWarning = (blockStyle) => getTemplate(`block style "${blockStyle}"`, 'block');
const unknownListStyleWarning = (listStyle) => getTemplate(`list style "${listStyle}"`, 'list');
const unknownListItemStyleWarning = (listStyle) => getTemplate(`list item style "${listStyle}"`, 'listItem');
function printWarning(message) {
console.warn(message);
}
class SpanComponent {
constructor() {
this.template = viewChild.required('spanTmpl');
this.#missingHandler = inject(MISSING_COMPONENT_HANDLER);
this.spanToPlainText = spanToPlainText;
this.trackBy = trackBy;
}
#missingHandler;
handleMissingComponent(markType) {
this.#missingHandler(unknownMarkWarning(markType), {
type: markType,
nodeType: 'mark',
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: SpanComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: SpanComponent, isStandalone: true, selector: "lib-span", viewQueries: [{ propertyName: "template", first: true, predicate: ["spanTmpl"], descendants: true, isSignal: true }], ngImport: i0, template: `
<ng-template
#spanTmpl
let-node
let-components="components"
let-renderNode="renderNode"
>
<ng-template #children>
<ng-container
*ngTemplateOutlet="
nodeChildren;
context: { $implicit: node, components, renderNode }
"
/>
</ng-template>
@if (components.marks?.[node.markType]) {
<ng-container
*ngComponentOutlet="
components.marks?.[node.markType];
inputs: {
childrenData: {
template: nodeChildren,
context: { $implicit: node, components, renderNode },
},
text: spanToPlainText(node),
value: node.markDef,
markKey: node.markKey,
markType: node.markType,
}
"
/>
} @else {
@switch (node.markType) {
@case ('strong') {
<strong><ng-container *ngTemplateOutlet="children" /></strong>
}
@case ('em') {
<em><ng-container *ngTemplateOutlet="children" /></em>
}
@case ('code') {
<code><ng-container *ngTemplateOutlet="children" /></code>
}
@case ('underline') {
<span style="text-decoration: underline"
><ng-container *ngTemplateOutlet="children"
/></span>
}
@case ('strike-through') {
<del><ng-container *ngTemplateOutlet="children" /></del>
}
@case ('link') {
<a [href]="node.markDef?.href"
><ng-container *ngTemplateOutlet="children"
/></a>
}
@default {
{{ handleMissingComponent(node.markType)
}}<span [class]="'unknown__pt__mark__' + node.markType"
><ng-container *ngTemplateOutlet="children"
/></span>
}
}
}
</ng-template>
<ng-template
#nodeChildren
let-node
let-components="components"
let-renderNode="renderNode"
>
@if (!node.children) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: { $implicit: node, isInline: true, components }
"
/>
} @else {
@for (
child of node.children;
track trackBy(child._key, index);
let index = $index
) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: { $implicit: child, isInline: true, components }
"
/>
}
}
</ng-template>
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: SpanComponent, decorators: [{
type: Component,
args: [{
selector: 'lib-span',
imports: [NgTemplateOutlet, NgComponentOutlet],
template: `
<ng-template
#spanTmpl
let-node
let-components="components"
let-renderNode="renderNode"
>
<ng-template #children>
<ng-container
*ngTemplateOutlet="
nodeChildren;
context: { $implicit: node, components, renderNode }
"
/>
</ng-template>
@if (components.marks?.[node.markType]) {
<ng-container
*ngComponentOutlet="
components.marks?.[node.markType];
inputs: {
childrenData: {
template: nodeChildren,
context: { $implicit: node, components, renderNode },
},
text: spanToPlainText(node),
value: node.markDef,
markKey: node.markKey,
markType: node.markType,
}
"
/>
} @else {
@switch (node.markType) {
@case ('strong') {
<strong><ng-container *ngTemplateOutlet="children" /></strong>
}
@case ('em') {
<em><ng-container *ngTemplateOutlet="children" /></em>
}
@case ('code') {
<code><ng-container *ngTemplateOutlet="children" /></code>
}
@case ('underline') {
<span style="text-decoration: underline"
><ng-container *ngTemplateOutlet="children"
/></span>
}
@case ('strike-through') {
<del><ng-container *ngTemplateOutlet="children" /></del>
}
@case ('link') {
<a [href]="node.markDef?.href"
><ng-container *ngTemplateOutlet="children"
/></a>
}
@default {
{{ handleMissingComponent(node.markType)
}}<span [class]="'unknown__pt__mark__' + node.markType"
><ng-container *ngTemplateOutlet="children"
/></span>
}
}
}
</ng-template>
<ng-template
#nodeChildren
let-node
let-components="components"
let-renderNode="renderNode"
>
@if (!node.children) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: { $implicit: node, isInline: true, components }
"
/>
} @else {
@for (
child of node.children;
track trackBy(child._key, index);
let index = $index
) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: { $implicit: child, isInline: true, components }
"
/>
}
}
</ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
}]
}] });
class ListComponent {
constructor() {
this.template = viewChild.required('listTmpl');
this.missingHandler = inject(MISSING_COMPONENT_HANDLER);
this.trackBy = trackBy;
}
handleMissingComponent(node) {
const style = node.listItem || 'bullet';
this.missingHandler(unknownListStyleWarning(style), {
nodeType: 'listStyle',
type: style,
});
}
getChildNode(child, index) {
return child._key ? child : { ...child, _key: `li-${index}` };
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: ListComponent, isStandalone: true, selector: "lib-list", viewQueries: [{ propertyName: "template", first: true, predicate: ["listTmpl"], descendants: true, isSignal: true }], ngImport: i0, template: `
<ng-template
#listTmpl
let-node
let-components="components"
let-renderNode="renderNode"
>
<ng-template #children>
<ng-container
*ngTemplateOutlet="
listChildren;
context: { node, components, renderNode }
"
/>
</ng-template>
@if (components.list?.[node.listItem]) {
<ng-container
*ngComponentOutlet="
components.list?.[node.listItem];
inputs: {
childrenData: {
template: listChildren,
context: { node, components, renderNode },
},
value: node,
isInline: false,
}
"
/>
} @else {
@switch (node.listItem) {
@case ('bullet') {
<ul>
<ng-container *ngTemplateOutlet="children" />
</ul>
}
@case ('number') {
<ol>
<ng-container *ngTemplateOutlet="children" />
</ol>
}
@default {
<ul>
<ng-container *ngTemplateOutlet="children" />{{
handleMissingComponent(node)
}}
</ul>
}
}
}
</ng-template>
<ng-template
#listChildren
let-node="node"
let-components="components"
let-renderNode="renderNode"
>
@for (
child of node.children;
track trackBy(child._key, index, 'li');
let index = $index
) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: {
$implicit: getChildNode(child, index),
index,
isInline: false,
components,
}
"
/>
}
</ng-template>
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ListComponent, decorators: [{
type: Component,
args: [{
selector: 'lib-list',
imports: [NgTemplateOutlet, NgComponentOutlet],
template: `
<ng-template
#listTmpl
let-node
let-components="components"
let-renderNode="renderNode"
>
<ng-template #children>
<ng-container
*ngTemplateOutlet="
listChildren;
context: { node, components, renderNode }
"
/>
</ng-template>
@if (components.list?.[node.listItem]) {
<ng-container
*ngComponentOutlet="
components.list?.[node.listItem];
inputs: {
childrenData: {
template: listChildren,
context: { node, components, renderNode },
},
value: node,
isInline: false,
}
"
/>
} @else {
@switch (node.listItem) {
@case ('bullet') {
<ul>
<ng-container *ngTemplateOutlet="children" />
</ul>
}
@case ('number') {
<ol>
<ng-container *ngTemplateOutlet="children" />
</ol>
}
@default {
<ul>
<ng-container *ngTemplateOutlet="children" />{{
handleMissingComponent(node)
}}
</ul>
}
}
}
</ng-template>
<ng-template
#listChildren
let-node="node"
let-components="components"
let-renderNode="renderNode"
>
@for (
child of node.children;
track trackBy(child._key, index, 'li');
let index = $index
) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: {
$implicit: getChildNode(child, index),
index,
isInline: false,
components,
}
"
/>
}
</ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
}]
}] });
class ListItemComponent {
constructor() {
this.template = viewChild.required('listItemTmpl');
this.getNodeWithoutListItem = (node) => {
// Wrap any other style in whatever the block serializer says to use
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { listItem, ...blockNode } = node;
return blockNode;
};
this.serializeBlock = serializeBlock;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: ListItemComponent, isStandalone: true, selector: "lib-list-item", viewQueries: [{ propertyName: "template", first: true, predicate: ["listItemTmpl"], descendants: true, isSignal: true }], ngImport: i0, template: `<ng-template
#listItemTmpl
let-node
let-index="index"
let-components="components"
let-renderNode="renderNode"
>
<ng-template #listItemChildren>
@if (node.style && node.style !== 'normal') {
<ng-container
*ngTemplateOutlet="
renderNode;
context: {
$implicit: getNodeWithoutListItem(node),
index,
isInline: false,
components,
}
"
/>
} @else {
@for (
child of serializeBlock({ node, isInline: false }).children;
track child._key
) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: { $implicit: child, isInline: true, components }
"
/>
}
}
</ng-template>
@if (components.listItem?.[node.listItem]) {
<ng-container
*ngComponentOutlet="
components.listItem?.[node.listItem];
inputs: {
childrenData: {
template: listItemChildren,
context: { node, index, components, renderNode },
},
value: node,
index,
isInline: false,
}
"
/>
} @else {
<li>
<ng-container *ngTemplateOutlet="listItemChildren" />
</li>
}
</ng-template>`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: ListItemComponent, decorators: [{
type: Component,
args: [{
selector: 'lib-list-item',
imports: [NgTemplateOutlet, NgComponentOutlet],
template: `<ng-template
#listItemTmpl
let-node
let-index="index"
let-components="components"
let-renderNode="renderNode"
>
<ng-template #listItemChildren>
@if (node.style && node.style !== 'normal') {
<ng-container
*ngTemplateOutlet="
renderNode;
context: {
$implicit: getNodeWithoutListItem(node),
index,
isInline: false,
components,
}
"
/>
} @else {
@for (
child of serializeBlock({ node, isInline: false }).children;
track child._key
) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: { $implicit: child, isInline: true, components }
"
/>
}
}
</ng-template>
@if (components.listItem?.[node.listItem]) {
<ng-container
*ngComponentOutlet="
components.listItem?.[node.listItem];
inputs: {
childrenData: {
template: listItemChildren,
context: { node, index, components, renderNode },
},
value: node,
index,
isInline: false,
}
"
/>
} @else {
<li>
<ng-container *ngTemplateOutlet="listItemChildren" />
</li>
}
</ng-template>`,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
}]
}] });
class PortableTextComponent {
constructor() {
this.value = input.required();
this.components = input({});
this.unknownBlockTmpl = viewChild.required('unknownBlock');
this.onMissingComponent = input(printWarning);
this.#container = inject(ViewContainerRef);
this.#injector = inject(Injector);
this.blockTemplate = computed(() => this.#container.createComponent(BlockComponent, {
injector: this.#injector,
}).instance);
this.listTemplate = computed(() => this.#container.createComponent(ListComponent, {
injector: this.#injector,
}).instance);
this.listItemTemplate = computed(() => this.#container.createComponent(ListItemComponent, {
injector: this.#injector,
}).instance);
this.spanTemplate = computed(() => this.#container.createComponent(SpanComponent, {
injector: this.#injector,
}).instance);
this.textTemplate = computed(() => this.#container.createComponent(TextComponent, {
injector: this.#injector,
}).instance);
this.nestedBlocks = computed(() => {
const blocks = Array.isArray(this.value()) ? this.value() : [this.value()];
return nestLists(blocks, LIST_NEST_MODE_HTML);
});
this.hasCustomComponentForNode = (node) => !!this.components().types?.[node._type];
this.getCustomComponentForNode = (node) => this.components().types?.[node._type];
this.isPortableTextToolkitList = isPortableTextToolkitList;
this.isPortableTextListItemBlock = isPortableTextListItemBlock;
this.isPortableTextBlock = isPortableTextBlock;
this.isPortableTextToolkitSpan = isPortableTextToolkitSpan;
this.isPortableTextToolkitTextNode = isPortableTextToolkitTextNode;
this.trackBy = trackBy;
}
#container;
#injector;
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: PortableTextComponent, isStandalone: true, selector: "[portable-text]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, components: { classPropertyName: "components", publicName: "components", isSignal: true, isRequired: false, transformFunction: null }, onMissingComponent: { classPropertyName: "onMissingComponent", publicName: "onMissingComponent", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.portable-text": "true" } }, providers: [
{
provide: MISSING_COMPONENT_HANDLER,
useFactory: (component) => component.onMissingComponent() || noop,
deps: [forwardRef(() => PortableTextComponent)],
},
], viewQueries: [{ propertyName: "unknownBlockTmpl", first: true, predicate: ["unknownBlock"], descendants: true, isSignal: true }], ngImport: i0, template: `
@for (
block of nestedBlocks();
track trackBy(block._key, index);
let index = $index
) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: {
$implicit: block,
isInline: false,
components: components(),
}
"
/>
}
<ng-template
#renderNode
let-node
let-index="index"
let-isInline="isInline"
let-components="components"
>
@if (isPortableTextToolkitList(node)) {
<ng-container
*ngTemplateOutlet="
listTemplate().template();
context: {
$implicit: node,
components,
renderNode,
}
"
/>
} @else if (isPortableTextListItemBlock(node)) {
<ng-container
*ngTemplateOutlet="
listItemTemplate().template();
context: {
$implicit: node,
index,
components,
renderNode,
}
"
/>
} @else if (isPortableTextToolkitSpan(node)) {
<ng-container
*ngTemplateOutlet="
spanTemplate().template();
context: {
$implicit: node,
components,
renderNode,
}
"
/>
} @else if (hasCustomComponentForNode(node)) {
<ng-container
*ngComponentOutlet="
getCustomComponentForNode(node);
inputs: { value: node, isInline }
"
/>
} @else if (isPortableTextBlock(node)) {
<ng-container
*ngTemplateOutlet="
blockTemplate().template();
context: { $implicit: node, isInline, components, renderNode }
"
/>
} @else if (isPortableTextToolkitTextNode(node)) {
<ng-container
*ngTemplateOutlet="
textTemplate().template();
context: { $implicit: node, components }
"
/>
} @else {
<ng-container
*ngTemplateOutlet="
unknownTypeTmpl;
context: { node, components, isInline }
"
/>
}
</ng-template>
<ng-template
#unknownTypeTmpl
let-value="node"
let-components="components"
let-isInline="isInline"
>
<ng-container
*ngTemplateOutlet="unknownBlock; context: { node: value, isInline }"
/>
</ng-template>
<ng-template #unknownBlock let-value="node" let-isInline="isInline">
@if (isInline) {
<span style="display: none">{{
'Unknown block type: ' + value._type
}}</span>
} @else {
<div style="display: none">
{{ 'Unknown block type: ' + value._type }}
</div>
}
</ng-template>
`, isInline: true, styles: [".portable-text{display:block}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextComponent, decorators: [{
type: Component,
args: [{ selector: '[portable-text]', imports: [NgTemplateOutlet, NgComponentOutlet], template: `
@for (
block of nestedBlocks();
track trackBy(block._key, index);
let index = $index
) {
<ng-container
*ngTemplateOutlet="
renderNode;
context: {
$implicit: block,
isInline: false,
components: components(),
}
"
/>
}
<ng-template
#renderNode
let-node
let-index="index"
let-isInline="isInline"
let-components="components"
>
@if (isPortableTextToolkitList(node)) {
<ng-container
*ngTemplateOutlet="
listTemplate().template();
context: {
$implicit: node,
components,
renderNode,
}
"
/>
} @else if (isPortableTextListItemBlock(node)) {
<ng-container
*ngTemplateOutlet="
listItemTemplate().template();
context: {
$implicit: node,
index,
components,
renderNode,
}
"
/>
} @else if (isPortableTextToolkitSpan(node)) {
<ng-container
*ngTemplateOutlet="
spanTemplate().template();
context: {
$implicit: node,
components,
renderNode,
}
"
/>
} @else if (hasCustomComponentForNode(node)) {
<ng-container
*ngComponentOutlet="
getCustomComponentForNode(node);
inputs: { value: node, isInline }
"
/>
} @else if (isPortableTextBlock(node)) {
<ng-container
*ngTemplateOutlet="
blockTemplate().template();
context: { $implicit: node, isInline, components, renderNode }
"
/>
} @else if (isPortableTextToolkitTextNode(node)) {
<ng-container
*ngTemplateOutlet="
textTemplate().template();
context: { $implicit: node, components }
"
/>
} @else {
<ng-container
*ngTemplateOutlet="
unknownTypeTmpl;
context: { node, components, isInline }
"
/>
}
</ng-template>
<ng-template
#unknownTypeTmpl
let-value="node"
let-components="components"
let-isInline="isInline"
>
<ng-container
*ngTemplateOutlet="unknownBlock; context: { node: value, isInline }"
/>
</ng-template>
<ng-template #unknownBlock let-value="node" let-isInline="isInline">
@if (isInline) {
<span style="display: none">{{
'Unknown block type: ' + value._type
}}</span>
} @else {
<div style="display: none">
{{ 'Unknown block type: ' + value._type }}
</div>
}
</ng-template>
`, host: { '[class.portable-text]': 'true' }, providers: [
{
provide: MISSING_COMPONENT_HANDLER,
useFactory: (component) => component.onMissingComponent() || noop,
deps: [forwardRef(() => PortableTextComponent)],
},
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, styles: [".portable-text{display:block}\n"] }]
}] });
const noop = () => {
/* empty */
};
// eslint-disable-next-line @angular-eslint/directive-selector
// eslint-disable-next-line @angular-eslint/directive-class-suffix
class DynamicPortableTextContent {
constructor() {
this.childrenData = input.required();
this.children = viewChild('children', {
read: ViewContainerRef,
});
}
ngAfterViewInit() {
this.children()?.createEmbeddedView(this.childrenData().template, this.childrenData().context);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: DynamicPortableTextContent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "19.0.3", type: DynamicPortableTextContent, isStandalone: true, selector: "[portableTextContent]", inputs: { childrenData: { classPropertyName: "childrenData", publicName: "childrenData", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "children", first: true, predicate: ["children"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: DynamicPortableTextContent, decorators: [{
type: Directive,
args: [{ selector: '[portableTextContent]', standalone: true }]
}] });
// eslint-disable-next-line @angular-eslint/directive-selector
/**
* @template M Shape describing the data associated with this mark, if it is an annotation
*/
// eslint-disable-next-line @angular-eslint/directive-class-suffix
class PortableTextMarkComponent extends DynamicPortableTextContent {
constructor() {
super(...arguments);
/**
* Mark definition, e.g. the actual data of the annotation. If the mark is a simple decorator, this will be `undefined`
*/
this.value = input();
/**
* Text content of this mark
*/
this.text = input.required();
/**
* Key for this mark. The same key can be used amongst multiple text spans within the same block, so don't rely on this for Angular keys.
*/
this.markKey = input();
/**
* Type of mark - ie value of `_type` in the case of annotations, or the name of the decorator otherwise - eg `em`, `italic`.
*/
this.markType = input.required();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextMarkComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.0.3", type: PortableTextMarkComponent, isStandalone: true, selector: "[portableTextMark]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null }, markKey: { classPropertyName: "markKey", publicName: "markKey", isSignal: true, isRequired: false, transformFunction: null }, markType: { classPropertyName: "markType", publicName: "markType", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextMarkComponent, decorators: [{
type: Directive,
args: [{ selector: '[portableTextMark]', standalone: true }]
}] });
// eslint-disable-next-line @angular-eslint/directive-selector
/**
* Data associated with this portable text node, eg the raw JSON value of a block/type
*/
// eslint-disable-next-line @angular-eslint/directive-class-suffix
class PortableTextTypeComponent extends DynamicPortableTextContent {
constructor() {
super(...arguments);
this.value = input.required();
/**
* Whether this node is "inline" - ie as a child of a text block,
* alongside text spans, or a block in and of itself.
*/
this.isInline = input.required();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextTypeComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.0.3", type: PortableTextTypeComponent, isStandalone: true, selector: "[portableTextType]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, isInline: { classPropertyName: "isInline", publicName: "isInline", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextTypeComponent, decorators: [{
type: Directive,
args: [{ selector: '[portableTextType]', standalone: true }]
}] });
// eslint-disable-next-line @angular-eslint/directive-selector
// eslint-disable-next-line @angular-eslint/directive-class-suffix
class PortableTextBlockComponent extends PortableTextTypeComponent {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextBlockComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.3", type: PortableTextBlockComponent, isStandalone: true, selector: "[portableTextBlock]", usesInheritance: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextBlockComponent, decorators: [{
type: Directive,
args: [{ selector: '[portableTextBlock]', standalone: true }]
}] });
// eslint-disable-next-line @angular-eslint/directive-selector
// eslint-disable-next-line @angular-eslint/directive-class-suffix
class PortableTextListComponent extends PortableTextTypeComponent {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextListComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.3", type: PortableTextListComponent, isStandalone: true, selector: "[portableTextListItem]", usesInheritance: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextListComponent, decorators: [{
type: Directive,
args: [{ selector: '[portableTextListItem]', standalone: true }]
}] });
// eslint-disable-next-line @angular-eslint/directive-selector
// eslint-disable-next-line @angular-eslint/directive-class-suffix
class PortableTextListItemComponent extends PortableTextTypeComponent {
constructor() {
super(...arguments);
this.index = input.required();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextListItemComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.0.3", type: PortableTextListItemComponent, isStandalone: true, selector: "[portableTextListItem]", inputs: { index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PortableTextListItemComponent, decorators: [{
type: Directive,
args: [{ selector: '[portableTextListItem]', standalone: true }]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { PortableTextBlockComponent, PortableTextComponent, PortableTextListComponent, PortableTextListItemComponent, PortableTextMarkComponent, PortableTextTypeComponent };
//# sourceMappingURL=limitless-angular-sanity-portabletext.mjs.map