@tachui/primitives
Version:
Basic UI components for tachUI framework
322 lines (321 loc) • 9.68 kB
JavaScript
import { withModifiers as a, ComponentWithCSSClasses as b, processElementOverride as w, createSignal as y, useLifecycle as C, ImageAsset as v, registerComponentWithLifecycleHooks as T, h as p, createEffect as E, ConcatenatedComponent as g, text as R } from "@tachui/core";
import { aspectRatio as S } from "@tachui/modifiers";
var I = Object.defineProperty, P = (t, e, i) => e in t ? I(t, e, { enumerable: !0, configurable: !0, writable: !0, value: i }) : t[e] = i, c = (t, e, i) => P(t, typeof e != "symbol" ? e + "" : e, i);
class m extends b {
constructor(e) {
super(), this.props = e, c(this, "type", "component"), c(this, "id"), c(this, "mounted", !1), c(this, "cleanup", []), c(this, "effectiveTag"), c(this, "validationResult"), c(this, "loadingStateSignal"), c(this, "setLoadingState"), this.id = `image-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const i = w("Image", "img", this.props.element);
this.effectiveTag = i.tag, this.validationResult = i.validation;
const o = this.props.src ? "idle" : "error", [n, r] = y(o);
this.loadingStateSignal = n, this.setLoadingState = r, C(this, {
onDOMReady: (s, f) => {
this.props.src instanceof v && f instanceof HTMLImageElement && this.setupImageAssetReactivityForDOMElement(
this.props.src,
f
);
}
}), T(this);
}
/**
* Set loading state and notify callback
*/
setLoadingStateWithCallback(e) {
this.setLoadingState(e), this.props.onLoadingStateChange && this.props.onLoadingStateChange(e);
}
/**
* Render the image component with reactive content handling
*/
render() {
const e = this.loadingStateSignal();
if (e === "loading" && this.props.placeholder) {
if (typeof this.props.placeholder == "string")
return [p("img", {
class: "tachui-image-placeholder",
src: this.props.placeholder,
alt: "Loading..."
})];
if (this.props.placeholder && typeof this.props.placeholder == "object")
return this.props.placeholder.render();
}
if (e === "error" && this.props.errorPlaceholder) {
if (typeof this.props.errorPlaceholder == "string")
return [p("img", {
class: "tachui-image-error",
src: this.props.errorPlaceholder,
alt: "Error loading image"
})];
if (this.props.errorPlaceholder && typeof this.props.errorPlaceholder == "object")
return this.props.errorPlaceholder.render();
}
const i = this.props.src instanceof v ? this.props.src.resolve() : this.props.src, o = ["tachui-image"], n = this.createClassString(this.props, o), r = p(this.effectiveTag, {
className: n,
src: i,
// Pass resolved src for initial render
alt: this.props.alt,
// Pass reactive alt directly
loading: this.props.loadingStrategy || "lazy",
crossorigin: this.props.crossOrigin,
decoding: this.props.decoding || "async",
fetchpriority: this.props.fetchPriority
});
return r.componentMetadata = {
id: this.id,
type: "Image",
originalType: "Image",
overriddenTo: this.effectiveTag !== "img" ? this.effectiveTag : void 0,
validationResult: this.validationResult
}, [r];
}
/**
* Set up ImageAsset reactivity for a real DOM element (called from onDOMReady)
*/
setupImageAssetReactivityForDOMElement(e, i) {
const o = E(() => {
const n = e.resolve();
i.src = n, this.setLoadingStateWithCallback("loading");
});
this.cleanup.push(() => o.dispose());
}
// ============================================================================
// Concatenation Support (Phase 3.1)
// ============================================================================
/**
* Concatenate this image with another concatenatable component
*/
concat(e) {
const i = this.toSegment(), o = e.toSegment(), n = {
totalSegments: e instanceof g ? e.segments.length + 1 : 2,
accessibilityRole: e instanceof g ? this.mergeAccessibilityRoles(
"group",
e.metadata.accessibilityRole
) : this.determineAccessibilityRole(e),
semanticStructure: "inline"
// Images are typically inline in concatenation
};
return new g([i, o], n);
}
/**
* Convert this image to a segment for concatenation
*/
toSegment() {
return {
id: this.id,
component: this,
modifiers: [],
// Images don't typically have concatenation-specific modifiers
render: () => {
const e = this.render();
return Array.isArray(e) ? e[0] : e;
}
};
}
/**
* Check if this component supports concatenation
*/
isConcatenatable() {
return !0;
}
/**
* Determine accessibility role for concatenation
*/
determineAccessibilityRole(e) {
switch (e.constructor.name) {
case "EnhancedText":
return "group";
// Image + Text = group
case "EnhancedImage":
return "group";
// Image + Image = group
case "EnhancedButton":
case "EnhancedLink":
return "composite";
// Image + Interactive = composite
default:
return "composite";
}
}
/**
* Merge accessibility roles when combining components
*/
mergeAccessibilityRoles(e, i) {
return e === "composite" || i === "composite" ? "composite" : "group";
}
}
function u(t, e = {}) {
const i = { ...e, src: t }, o = new m(i), n = a(o);
return n.scaledToFit = function() {
const r = new m({
...i,
aspectRatio: void 0,
contentMode: "fit"
}), s = a(r);
return s.scaledToFit = n.scaledToFit, s.scaledToFill = n.scaledToFill, s.modifiers.push(S(void 0, "fit")), s;
}, n.scaledToFill = function() {
const r = new m({
...i,
aspectRatio: void 0,
contentMode: "fill"
}), s = a(r);
return s.scaledToFit = n.scaledToFit, s.scaledToFill = n.scaledToFill, s.modifiers.push(S(void 0, "fill")), s;
}, n;
}
const H = {
idle: "idle",
loading: "loading",
loaded: "loaded",
error: "error"
}, A = {
fit: "fit",
fill: "fill",
stretch: "stretch",
center: "center",
scaleDown: "scaleDown"
}, $ = {
/**
* Create a responsive image with multiple sources
*/
responsive(t, e, i = {}) {
const o = t.map((n) => {
const r = [n.src];
return n.width && r.push(`${n.width}w`), r.join(" ");
}).join(", ");
return u(e, { ...i, srcSet: o });
},
/**
* Create an image with progressive loading
*/
progressive(t, e, i = {}) {
return u(t, {
...i,
lowQualitySrc: t,
highQualitySrc: e
});
},
/**
* Create an image with loading placeholder
*/
withPlaceholder(t, e, i = {}) {
return u(t, {
...i,
placeholder: e
});
}
};
var F = Object.defineProperty, L = (t, e, i) => e in t ? F(t, e, { enumerable: !0, configurable: !0, writable: !0, value: i }) : t[e] = i, h = (t, e, i) => L(t, typeof e != "symbol" ? e + "" : e, i);
class l {
constructor(e, i, o, n = {}) {
this.props = e, this.tag = i, this.content = o, this.attributes = n, h(this, "type", "component"), h(this, "id"), h(this, "mounted", !1), h(this, "cleanup", []), this.id = `element-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
render() {
return [
p(this.tag, this.attributes, this.content ? R(this.content) : "")
];
}
}
const d = {
/**
* Create a div element with modifier support
*/
div: (t = {}) => {
const e = new l(
t,
"div",
t.children ? String(t.children) : void 0
);
return a(e);
},
/**
* Create a span element with modifier support
*/
span: (t = {}) => {
const e = new l(
t,
"span",
t.children ? String(t.children) : void 0
);
return a(e);
},
/**
* Create a paragraph element with modifier support
*/
p: (t = {}) => {
const e = new l(
t,
"p",
t.children ? String(t.children) : void 0
);
return a(e);
},
/**
* Create a button element with modifier support
*
* Note: For enhanced button features (press states, variants, accessibility),
* use the main Button component instead.
*/
button: (t = {}) => {
const e = new l(
t,
"button",
t.children ? String(t.children) : void 0,
{
onclick: t.onClick
}
);
return process.env.NODE_ENV === "test" && (e.props || (e.props = {}), e.props.tabIndex = 0), a(e);
},
/**
* Create an input element with modifier support
*/
input: (t = {}) => {
const e = new l(t, "input", void 0, {
type: t.type || "text",
value: t.value || "",
placeholder: t.placeholder || "",
oninput: (i) => {
const o = i.target;
t.onChange?.(o.value);
}
});
return a(e);
},
/**
* Create an image element with modifier support
*
* Note: For enhanced image features (loading states, content modes, progressive loading),
* use the main Image component instead.
*/
img: (t) => {
const e = new l(t, "img", void 0, {
src: t.src,
alt: t.alt || "",
width: t.width,
height: t.height
});
return a(e);
},
/**
* Create a heading element with modifier support
*/
heading: (t) => (e = {}) => {
const i = new l(
e,
`h${t}`,
e.children ? String(e.children) : void 0
);
return a(i);
}
}, D = d.heading(1), O = d.heading(2), x = d.heading(3), N = d.heading(4), W = d.heading(5), j = d.heading(6);
export {
m as E,
d as H,
u as I,
H as a,
A as b,
$ as c,
D as d,
O as e,
x as f,
N as g,
W as h,
j as i
};