@cossackframework/renderer 0.7.0 → 0.7.4
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/README.md +103 -1
- package/dist/component.d.ts +4 -0
- package/dist/cossack-element.d.ts +10 -0
- package/dist/cossack-html-CnATUTdE.js +8166 -0
- package/dist/cossack-html.d.ts +16 -4
- package/dist/css.d.ts +23 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -3
- package/dist/server.d.ts +4 -0
- package/dist/server.js +11 -11
- package/package.json +5 -2
- package/dist/cossack-html-D6DeVgtW.js +0 -993
package/README.md
CHANGED
|
@@ -129,6 +129,108 @@ import { unsafeHTML } from '@cossackframework/renderer';
|
|
|
129
129
|
html`<div>${unsafeHTML('<script>...</script>')}</div>`
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
+
### SVG Fragments
|
|
133
|
+
|
|
134
|
+
Use `svg` for fragments whose root nodes must be created in the SVG namespace.
|
|
135
|
+
SVG results can be nested, rendered in arrays, and used inside an HTML `<svg>`
|
|
136
|
+
element. The renderer switches back to the HTML namespace inside
|
|
137
|
+
`<foreignObject>`.
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import { html, svg } from '@cossackframework/renderer';
|
|
141
|
+
|
|
142
|
+
const dot = (x: number, color: string) => svg`
|
|
143
|
+
<circle cx="${x}" cy="12" r="6" fill="${color}"></circle>
|
|
144
|
+
`;
|
|
145
|
+
|
|
146
|
+
html`<svg viewBox="0 0 100 24">${[dot(12, 'red'), dot(32, 'blue')]}</svg>`
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
SVG and HTML templates serialize the same way during SSR. Namespace selection
|
|
150
|
+
is a client DOM concern and is preserved during hydration.
|
|
151
|
+
|
|
152
|
+
### Rendering Nothing
|
|
153
|
+
|
|
154
|
+
`nothing` removes the value according to its binding context. An empty string
|
|
155
|
+
also renders no child node, but remains an ordinary value in attributes.
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { html, nothing } from '@cossackframework/renderer';
|
|
159
|
+
|
|
160
|
+
html`
|
|
161
|
+
<p>${showMessage ? message : nothing}</p>
|
|
162
|
+
<a title="prefix-${hasTitle ? title : nothing}">link</a>
|
|
163
|
+
<input .value=${hasValue ? value : nothing}>
|
|
164
|
+
<button ?disabled=${busy ? true : nothing}>Save</button>
|
|
165
|
+
<button @click=${enabled ? this.save : nothing}>Save</button>
|
|
166
|
+
<div ...=${enabled ? attributes : nothing}></div>
|
|
167
|
+
`
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
In child expressions, `nothing` clears managed nodes. In normal attributes it
|
|
171
|
+
removes the whole attribute, including an attribute with several expressions.
|
|
172
|
+
Property bindings receive `undefined`, boolean attributes are removed, event
|
|
173
|
+
handlers are disabled, and a spread set to `nothing` removes its previously
|
|
174
|
+
managed values. SSR, hydration, and later updates use the same rules.
|
|
175
|
+
|
|
176
|
+
## Component Styles
|
|
177
|
+
|
|
178
|
+
Declare Light DOM component styles with `static styles`. The `css` tag accepts
|
|
179
|
+
only numbers and nested `CSSResult` values in interpolations. Raw values require
|
|
180
|
+
the explicit `unsafeCSS` trust boundary.
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import {
|
|
184
|
+
CossackElement,
|
|
185
|
+
css,
|
|
186
|
+
html,
|
|
187
|
+
unsafeCSS,
|
|
188
|
+
} from '@cossackframework/renderer';
|
|
189
|
+
|
|
190
|
+
const gap = 12;
|
|
191
|
+
const shared = css`.label { font-weight: 600; }`;
|
|
192
|
+
const reviewedThemeColor = unsafeCSS('rebeccapurple');
|
|
193
|
+
|
|
194
|
+
class Notice extends CossackElement {
|
|
195
|
+
static styles = [
|
|
196
|
+
shared,
|
|
197
|
+
css`
|
|
198
|
+
.notice { display: flex; gap: ${gap}px; color: ${reviewedThemeColor}; }
|
|
199
|
+
@media (width < 40rem) { .notice { display: block; } }
|
|
200
|
+
@keyframes enter { from { opacity: 0; } }
|
|
201
|
+
.notice { animation: enter 150ms; }
|
|
202
|
+
`,
|
|
203
|
+
];
|
|
204
|
+
|
|
205
|
+
render() {
|
|
206
|
+
return html`<div class="notice"><span class="label">Ready</span></div>`;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Style arrays may be nested. They are flattened in declaration order, and the
|
|
212
|
+
last occurrence of the same `CSSResult` wins. A subclass can extend inherited
|
|
213
|
+
styles explicitly:
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
class EmphasizedNotice extends Notice {
|
|
217
|
+
static styles = [Notice.styles, css`.notice { border: 2px solid currentColor; }`];
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Cossack scopes selectors by adding deterministic `data-cossack-scope`
|
|
222
|
+
attributes to elements created by that component and emits one managed style
|
|
223
|
+
element per component instance. Conditional at-rules and functional selectors
|
|
224
|
+
are scoped recursively; keyframe names and matching animation declarations are
|
|
225
|
+
rewritten. `:host`, `:host-context`, and `::slotted` are rejected because
|
|
226
|
+
Cossack uses Light DOM rather than Shadow DOM.
|
|
227
|
+
|
|
228
|
+
Scoping follows template ownership. Nested components use their own scope, while
|
|
229
|
+
projected templates retain the scope of the component that created them. This
|
|
230
|
+
is attribute-based isolation, not a Shadow DOM security boundary: inherited CSS
|
|
231
|
+
properties still inherit normally. `unsafeHTML` and manually supplied DOM nodes
|
|
232
|
+
are explicit escape hatches and are not guaranteed to receive scope attributes.
|
|
233
|
+
|
|
132
234
|
## Using Components in Templates
|
|
133
235
|
|
|
134
236
|
Use the `component` helper function to include child components in your templates.
|
|
@@ -441,4 +543,4 @@ class Card extends CossackElement {
|
|
|
441
543
|
`;
|
|
442
544
|
}
|
|
443
545
|
}
|
|
444
|
-
```
|
|
546
|
+
```
|
package/dist/component.d.ts
CHANGED
|
@@ -4,5 +4,9 @@ export interface ComponentResult {
|
|
|
4
4
|
clazz: new () => CossackElement;
|
|
5
5
|
props: Record<string, unknown>;
|
|
6
6
|
children: unknown;
|
|
7
|
+
/** Rendering owner captured when component() is evaluated. */
|
|
8
|
+
parent?: CossackElement | null;
|
|
9
|
+
/** Framework-private scope captured from the rendering owner. */
|
|
10
|
+
serviceScope?: unknown;
|
|
7
11
|
}
|
|
8
12
|
export declare const isComponentResult: (value: unknown) => value is ComponentResult;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TemplateResult } from './cossack-html';
|
|
2
2
|
import { Context } from './context';
|
|
3
|
+
import type { CSSResultGroup } from './css';
|
|
3
4
|
export type PropertyDeclaration = {
|
|
4
5
|
type?: unknown;
|
|
5
6
|
reflect?: boolean;
|
|
@@ -28,6 +29,7 @@ export declare class CossackElement implements ReactiveControllerHost {
|
|
|
28
29
|
static properties: PropertyDeclarations;
|
|
29
30
|
static readonly _isCossackElement = true;
|
|
30
31
|
static components: Record<string, typeof CossackElement>;
|
|
32
|
+
static styles?: CSSResultGroup;
|
|
31
33
|
children: unknown;
|
|
32
34
|
props: Record<string, unknown>;
|
|
33
35
|
__parent: CossackElement | null;
|
|
@@ -56,6 +58,14 @@ export declare class CossackElement implements ReactiveControllerHost {
|
|
|
56
58
|
private __notifyListeners;
|
|
57
59
|
addRenderListener(listener: (template: TemplateResult | unknown | null) => void): void;
|
|
58
60
|
removeRenderListener(listener: (template: TemplateResult | unknown | null) => void): void;
|
|
61
|
+
/** @internal Return the deterministic Light DOM style scope for this class. */
|
|
62
|
+
_getStyleScopeId(): string | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* @internal Shared output finalizer used by standalone elements, nested
|
|
65
|
+
* component() rendering, and the core Cossack page/layout/app path.
|
|
66
|
+
*/
|
|
67
|
+
_finalizeRenderOutput(value: TemplateResult | unknown | null): TemplateResult | unknown | null;
|
|
68
|
+
private _claimTemplateOwnership;
|
|
59
69
|
mount(container: HTMLElement, hydrateFirst?: boolean): void;
|
|
60
70
|
addEventListener(type: string, callback: EventListenerOrEventListenerObject | null, _options?: boolean | AddEventListenerOptions): void;
|
|
61
71
|
removeEventListener(type: string, callback: EventListenerOrEventListenerObject | null, _options?: boolean | EventListenerOptions): void;
|