poseui 0.0.3 → 0.0.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/dist/index.d.ts +22 -1
- package/dist/index.js +41 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -46,6 +46,9 @@ type Child<TProps> = ChildValue | ((props: TProps) => ChildValue);
|
|
|
46
46
|
type RenderReturn<TSchema extends StandardSchemaV1 | undefined> = TSchema extends StandardSchemaV1 ? ReturnType<TSchema["~standard"]["validate"]> extends Promise<any> ? Promise<string> : string : string;
|
|
47
47
|
type CallArgs<TProps extends Record<string, unknown>, TSchema> = TSchema extends StandardSchemaV1 ? [TProps?] : [keyof TProps] extends [never] ? [TProps?] : [TProps];
|
|
48
48
|
type ClassEntry<TProps> = string | ((props: TProps) => string);
|
|
49
|
+
/** null means the attribute is omitted from the rendered output */
|
|
50
|
+
type AttrValue = string | null;
|
|
51
|
+
type AttrRecord<TProps> = Record<string, Dyn<TProps, AttrValue>>;
|
|
49
52
|
interface PoseElement<TProps extends Record<string, unknown>, TSchema extends StandardSchemaV1 | undefined = undefined> {
|
|
50
53
|
(...args: CallArgs<TProps, TSchema>): RenderReturn<TSchema>;
|
|
51
54
|
readonly classes: ReadonlyArray<ClassEntry<TProps>>;
|
|
@@ -798,6 +801,24 @@ interface PoseElement<TProps extends Record<string, unknown>, TSchema extends St
|
|
|
798
801
|
*/
|
|
799
802
|
when(pred: (props: TProps) => boolean, apply: (b: PoseElement<TProps, undefined>) => PoseElement<TProps, any>): PoseElement<TProps, TSchema>;
|
|
800
803
|
when<K extends keyof TProps>(key: K, cases: Partial<Record<TProps[K] & PropertyKey, (b: PoseElement<TProps, undefined>) => PoseElement<TProps, any>>>): PoseElement<TProps, TSchema>;
|
|
804
|
+
/**
|
|
805
|
+
* Set a single HTML attribute. Value can be static or derived from props.
|
|
806
|
+
* Pass `null` to omit the attribute.
|
|
807
|
+
*
|
|
808
|
+
* @example
|
|
809
|
+
* pose.as('a').attr('href', ({ url }) => url).attr('target', '_blank')
|
|
810
|
+
*/
|
|
811
|
+
attr(name: string, value: Dyn<TProps, AttrValue>): PoseElement<TProps, TSchema>;
|
|
812
|
+
/**
|
|
813
|
+
* Set multiple HTML attributes at once. Each value can be static or a
|
|
814
|
+
* `(props) => string | null` function. `null` omits the attribute.
|
|
815
|
+
*
|
|
816
|
+
* @example
|
|
817
|
+
* pose.as('input').attrs({ type: 'text', name: ({ field }) => field, required: ({ req }) => req ? '' : null })
|
|
818
|
+
* // or with a props function for multi-field logic:
|
|
819
|
+
* pose.as('a').attrs(({ url, external }) => ({ href: url, target: external ? '_blank' : null }))
|
|
820
|
+
*/
|
|
821
|
+
attrs(record: AttrRecord<TProps> | ((props: TProps) => Record<string, AttrValue>)): PoseElement<TProps, TSchema>;
|
|
801
822
|
/**
|
|
802
823
|
* Append any raw Tailwind class — static or derived from props.
|
|
803
824
|
* @example
|
|
@@ -825,4 +846,4 @@ interface Pose {
|
|
|
825
846
|
declare const pose: Pose;
|
|
826
847
|
declare const div: PoseElement<Record<never, never>, undefined>;
|
|
827
848
|
//#endregion
|
|
828
|
-
export { Child, ChildValue, Dyn, Pose, PoseElement, PoseValidationError, StandardSchemaV1, pose as default, div };
|
|
849
|
+
export { AttrRecord, AttrValue, Child, ChildValue, Dyn, Pose, PoseElement, PoseValidationError, StandardSchemaV1, pose as default, div };
|
package/dist/index.js
CHANGED
|
@@ -29,6 +29,25 @@ function arbitrary(value) {
|
|
|
29
29
|
function resolveClasses(classes, props) {
|
|
30
30
|
return classes.map((c) => typeof c === "function" ? c(props) : c).filter(Boolean).join(" ");
|
|
31
31
|
}
|
|
32
|
+
function renderAttrPair(name, value) {
|
|
33
|
+
if (value === null) return "";
|
|
34
|
+
return value === "" ? name : `${name}="${value}"`;
|
|
35
|
+
}
|
|
36
|
+
function resolveAttrs(attrs, props) {
|
|
37
|
+
const parts = [];
|
|
38
|
+
for (const entry of attrs) if (entry[0] === "single") {
|
|
39
|
+
const [, name, value] = entry;
|
|
40
|
+
const rendered = renderAttrPair(name, typeof value === "function" ? value(props) : value);
|
|
41
|
+
if (rendered) parts.push(rendered);
|
|
42
|
+
} else {
|
|
43
|
+
const [, fn] = entry;
|
|
44
|
+
for (const [name, value] of Object.entries(fn(props))) {
|
|
45
|
+
const rendered = renderAttrPair(name, value);
|
|
46
|
+
if (rendered) parts.push(rendered);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return parts.join(" ");
|
|
50
|
+
}
|
|
32
51
|
function renderChild(child, props) {
|
|
33
52
|
if (typeof child === "function") return renderChild(child(props), props);
|
|
34
53
|
if (Array.isArray(child)) return child.filter((c) => c != null).map((c) => renderChild(c, props)).join("");
|
|
@@ -40,15 +59,17 @@ function createBlankBuilder() {
|
|
|
40
59
|
return createBuilder({
|
|
41
60
|
tag: "div",
|
|
42
61
|
classes: [],
|
|
62
|
+
attrs: [],
|
|
43
63
|
children: [],
|
|
44
64
|
schema: void 0
|
|
45
65
|
});
|
|
46
66
|
}
|
|
47
67
|
function createBuilder(state) {
|
|
48
|
-
function derive(extraClasses = [], extraChildren = []) {
|
|
68
|
+
function derive(extraClasses = [], extraChildren = [], extraAttrs = []) {
|
|
49
69
|
return createBuilder({
|
|
50
70
|
...state,
|
|
51
71
|
classes: [...state.classes, ...extraClasses],
|
|
72
|
+
attrs: [...state.attrs, ...extraAttrs],
|
|
52
73
|
children: [...state.children, ...extraChildren]
|
|
53
74
|
});
|
|
54
75
|
}
|
|
@@ -64,9 +85,11 @@ function createBuilder(state) {
|
|
|
64
85
|
}
|
|
65
86
|
function buildHtml(resolvedProps) {
|
|
66
87
|
const classStr = resolveClasses(state.classes, resolvedProps);
|
|
88
|
+
const attrsStr = resolveAttrs(state.attrs, resolvedProps);
|
|
67
89
|
const childrenStr = state.children.map((c) => renderChild(c, resolvedProps)).join("");
|
|
68
90
|
const classAttr = classStr ? ` class="${classStr}"` : "";
|
|
69
|
-
|
|
91
|
+
const attrsAttr = attrsStr ? ` ${attrsStr}` : "";
|
|
92
|
+
return `<${state.tag}${classAttr}${attrsAttr}>${childrenStr}</${state.tag}>`;
|
|
70
93
|
}
|
|
71
94
|
function render(...args) {
|
|
72
95
|
const props = args[0] ?? {};
|
|
@@ -85,6 +108,7 @@ function createBuilder(state) {
|
|
|
85
108
|
el.input = (schema) => createBuilder({
|
|
86
109
|
tag: state.tag,
|
|
87
110
|
classes: state.classes,
|
|
111
|
+
attrs: state.attrs,
|
|
88
112
|
children: state.children,
|
|
89
113
|
schema
|
|
90
114
|
});
|
|
@@ -491,6 +515,19 @@ function createBuilder(state) {
|
|
|
491
515
|
});
|
|
492
516
|
}
|
|
493
517
|
};
|
|
518
|
+
el.attr = (name, value) => derive([], [], [[
|
|
519
|
+
"single",
|
|
520
|
+
name,
|
|
521
|
+
value
|
|
522
|
+
]]);
|
|
523
|
+
el.attrs = (recordOrFn) => {
|
|
524
|
+
if (typeof recordOrFn === "function") return derive([], [], [["record", recordOrFn]]);
|
|
525
|
+
return derive([], [], Object.entries(recordOrFn).map(([name, value]) => [
|
|
526
|
+
"single",
|
|
527
|
+
name,
|
|
528
|
+
value
|
|
529
|
+
]));
|
|
530
|
+
};
|
|
494
531
|
el.cls = (value) => typeof value === "function" ? derive([value]) : derive([value]);
|
|
495
532
|
el.render = async (props, opts) => {
|
|
496
533
|
const html = render(props);
|
|
@@ -504,6 +541,7 @@ function createBuilder(state) {
|
|
|
504
541
|
el.child = (value) => createBuilder({
|
|
505
542
|
...state,
|
|
506
543
|
classes: [...state.classes],
|
|
544
|
+
attrs: [...state.attrs],
|
|
507
545
|
children: [...state.children, value]
|
|
508
546
|
});
|
|
509
547
|
return el;
|
|
@@ -520,6 +558,7 @@ const pose = { as(tag) {
|
|
|
520
558
|
return createBuilder({
|
|
521
559
|
tag,
|
|
522
560
|
classes: [],
|
|
561
|
+
attrs: [],
|
|
523
562
|
children: [],
|
|
524
563
|
schema: void 0
|
|
525
564
|
});
|