amateras 0.13.2 → 0.14.0
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 +39 -38
- package/build/core.js +1 -1
- package/build/css-keyframes.js +1 -0
- package/build/css-property.js +1 -0
- package/build/css-variable.js +1 -0
- package/build/for.js +1 -1
- package/build/i18n.js +1 -1
- package/build/if.js +1 -1
- package/build/import-map.js +1 -1
- package/build/match.js +1 -1
- package/build/meta.js +1 -1
- package/build/prefetch.js +1 -1
- package/build/router.js +1 -1
- package/build/signal.js +1 -1
- package/build/store.js +1 -1
- package/build/ui.js +1 -1
- package/build/utils.js +1 -1
- package/build/widget.js +1 -1
- package/package.json +3 -2
- package/packages/core/src/index.ts +86 -31
- package/packages/core/src/lib/hmr.ts +4 -4
- package/packages/core/src/structure/ElementProto.ts +33 -11
- package/packages/core/src/structure/GlobalState.ts +13 -4
- package/packages/core/src/structure/NodeProto.ts +2 -4
- package/packages/core/src/structure/Proto.ts +37 -23
- package/packages/core/src/structure/TextProto.ts +1 -2
- package/packages/css/README.md +18 -15
- package/packages/css/src/ext/property.ts +2 -3
- package/packages/css/src/index.ts +1 -1
- package/packages/css/src/structure/$CSSProperty.ts +4 -0
- package/packages/css/src/structure/$CSSVariable.ts +1 -1
- package/packages/css/src/types.ts +5 -0
- package/packages/for/src/global.ts +12 -3
- package/packages/for/src/structure/For.ts +5 -3
- package/packages/i18n/README.md +16 -24
- package/packages/i18n/src/index.ts +26 -5
- package/packages/i18n/src/structure/I18n.ts +2 -4
- package/packages/i18n/src/structure/I18nSession.ts +4 -2
- package/packages/i18n/src/structure/I18nTranslation.ts +15 -26
- package/packages/idb/src/structure/$IDBStore.ts +2 -2
- package/packages/if/src/global.ts +15 -4
- package/packages/if/src/index.ts +18 -8
- package/packages/if/src/structure/Condition.ts +16 -13
- package/packages/if/src/structure/ConditionStatement.ts +9 -9
- package/packages/match/src/global.ts +9 -3
- package/packages/match/src/structure/Match.ts +1 -1
- package/packages/meta/src/index.ts +4 -5
- package/packages/prefetch/src/index.ts +30 -9
- package/packages/router/src/global.ts +17 -4
- package/packages/router/src/index.ts +25 -18
- package/packages/router/src/structure/Route.ts +2 -1
- package/packages/router/src/structure/RouteNode.ts +8 -6
- package/packages/router/src/structure/RouteSlot.ts +15 -2
- package/packages/router/src/structure/Router.ts +28 -19
- package/packages/router/src/structure/RouterConstructor.ts +5 -5
- package/packages/router/src/types.ts +2 -2
- package/packages/signal/README.md +28 -48
- package/packages/signal/src/index.ts +61 -38
- package/packages/signal/src/structure/Signal.ts +40 -7
- package/packages/store/src/structure/Store.ts +1 -1
- package/packages/ui/package.json +2 -1
- package/packages/ui/src/icon/check.svg.ts +1 -0
- package/packages/ui/src/icon/x.svg.ts +1 -0
- package/packages/ui/src/index.ts +9 -2
- package/packages/ui/src/lib/combobox_style.ts +20 -0
- package/packages/ui/src/lib/hover.ts +2 -0
- package/packages/ui/src/structure/Badge.ts +10 -1
- package/packages/ui/src/structure/Button.ts +54 -27
- package/packages/ui/src/structure/Card.ts +3 -4
- package/packages/ui/src/structure/Combobox/Combobox.ts +312 -0
- package/packages/ui/src/structure/Combobox/ComboboxChips.ts +178 -0
- package/packages/ui/src/structure/Combobox/ComboboxList.ts +209 -0
- package/packages/ui/src/structure/ContextMenu.ts +89 -0
- package/packages/ui/src/structure/Field.ts +109 -0
- package/packages/ui/src/structure/Input.ts +29 -0
- package/packages/ui/src/structure/Select/Select.ts +18 -8
- package/packages/ui/src/structure/Select/SelectContent.ts +6 -1
- package/packages/ui/src/structure/Select/SelectItem.ts +2 -1
- package/packages/ui/src/structure/Slideshow.ts +2 -2
- package/packages/ui/src/structure/Switch.ts +45 -0
- package/packages/ui/src/structure/Tabs.ts +3 -3
- package/packages/ui/src/structure/Toggle.ts +155 -0
- package/packages/ui/src/structure/Waterfall.ts +1 -1
- package/packages/ui/src/structure/WaterfallItem.ts +1 -1
- package/packages/utils/src/lib/utils.ts +30 -8
- package/packages/utils/src/structure/UID.ts +1 -1
- package/packages/widget/src/index.ts +29 -9
- package/packages/widget/src/structure/Widget.ts +7 -3
- package/packages/ui/src/structure/TextBlock.ts +0 -11
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { computeCleanup, track, trackSet, untrack, type UntrackFunction } from "#lib/track";
|
|
2
2
|
import { Signal } from "#structure/Signal";
|
|
3
|
-
import { GlobalState, TextProto } from "@amateras/core";
|
|
4
|
-
import { _instanceof, _Object_assign,
|
|
3
|
+
import { GlobalState, Proto, ProxyProto, TextProto } from "@amateras/core";
|
|
4
|
+
import { _instanceof, _Object_assign, forEach, _null, isString, _undefined, isBoolean, isNumber } from "@amateras/utils";
|
|
5
5
|
|
|
6
6
|
declare global {
|
|
7
|
-
export function $<T>(signal: Signal<T>): Signal<T>;
|
|
8
|
-
|
|
9
7
|
export namespace $ {
|
|
10
8
|
export function signal<T>(value: T): SignalTypes<T>;
|
|
11
|
-
export function effect(callback: (untrack: UntrackFunction) => void): void;
|
|
12
|
-
export function compute<T>(callback: (untrack: UntrackFunction) => T):
|
|
9
|
+
export function effect(callback: (untrack: UntrackFunction) => void, signals?: Signal[]): void;
|
|
10
|
+
export function compute<T>(callback: (untrack: UntrackFunction) => T): SignalTypes<T>;
|
|
13
11
|
export function optional<T>(signal: Signal<T | undefined | null> | Signal<T | null> | Signal<T | undefined>): Signal<NonNullable<T>> | null
|
|
14
|
-
export function resolve<T>(value: T, handle?: (value: T extends
|
|
12
|
+
export function resolve<T>(value: T, handle?: (value: T extends Signal<infer K> | SignalObject<infer K> ? K : T) => void): T;
|
|
13
|
+
|
|
14
|
+
export interface Overload<I> {
|
|
15
|
+
signal: [
|
|
16
|
+
input: [Signal],
|
|
17
|
+
output: TextProto,
|
|
18
|
+
args: []
|
|
19
|
+
]
|
|
20
|
+
}
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
export type OrSignal<T = any> = T | SignalTypes<T>
|
|
@@ -23,17 +29,22 @@ declare module '@amateras/core' {
|
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
|
|
26
|
-
export type SignalTypes<T> =
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
export type SignalTypes<T> =
|
|
33
|
+
[ResolveNestedSignal<T>] extends [infer Resolved]
|
|
34
|
+
? [Resolved] extends [object]
|
|
35
|
+
? SignalObject<Resolved>
|
|
36
|
+
: Signal<Resolved>
|
|
37
|
+
: never;
|
|
38
|
+
|
|
39
|
+
type ResolveNestedSignal<T> = T extends Signal<infer R> | SignalObject<infer R> ? ResolveNestedSignal<R> : T;
|
|
29
40
|
|
|
30
41
|
export type SignalObject<T> = Signal<T> & {
|
|
31
|
-
[key in keyof T as Exclude<T[key], undefined> extends Function ? never : `${string & key}$`]: SignalTypes<T[key]>
|
|
42
|
+
[key in keyof T as Exclude<T[key], undefined> extends Signal ? `${string & key}` : Exclude<T[key], undefined> extends Function ? never : `${string & key}$`]: T[key] extends Signal ? T[key] : SignalTypes<T[key]>
|
|
32
43
|
}
|
|
33
44
|
|
|
34
|
-
GlobalState.assign({
|
|
45
|
+
GlobalState.assign(() => ({
|
|
35
46
|
signals: new Set()
|
|
36
|
-
})
|
|
47
|
+
}))
|
|
37
48
|
|
|
38
49
|
GlobalState.disposers.add(global => {
|
|
39
50
|
forEach(global.signals, signal => signal.dispose());
|
|
@@ -46,9 +57,11 @@ _Object_assign($, {
|
|
|
46
57
|
effect(
|
|
47
58
|
callback: (
|
|
48
59
|
untrack: UntrackFunction
|
|
49
|
-
) => void
|
|
60
|
+
) => void,
|
|
61
|
+
signals: Signal[] = []
|
|
50
62
|
) {
|
|
51
63
|
track(callback);
|
|
64
|
+
forEach(signals, signal => trackSet.add(signal));
|
|
52
65
|
forEach(trackSet, signal => signal.subscribe(_ => callback(untrack)));
|
|
53
66
|
trackSet.clear();
|
|
54
67
|
},
|
|
@@ -60,7 +73,12 @@ _Object_assign($, {
|
|
|
60
73
|
) {
|
|
61
74
|
let result = track(callback);
|
|
62
75
|
let compute = $.signal(result);
|
|
63
|
-
|
|
76
|
+
let proto = Proto.proto;
|
|
77
|
+
compute.exec = () => {
|
|
78
|
+
$.context(Proto, proto, () => {
|
|
79
|
+
compute.set(callback(untrack));
|
|
80
|
+
})
|
|
81
|
+
}
|
|
64
82
|
forEach(trackSet, signal => {
|
|
65
83
|
signal.computes = signal.computes ?? new Set();
|
|
66
84
|
let ref = new WeakRef(compute);
|
|
@@ -80,7 +98,7 @@ _Object_assign($, {
|
|
|
80
98
|
if (_instanceof(value, Signal<any>)) {
|
|
81
99
|
if (handle) {
|
|
82
100
|
value.subscribe(handle);
|
|
83
|
-
handle(value);
|
|
101
|
+
handle(value.value);
|
|
84
102
|
}
|
|
85
103
|
return value.value
|
|
86
104
|
}
|
|
@@ -89,36 +107,41 @@ _Object_assign($, {
|
|
|
89
107
|
}
|
|
90
108
|
})
|
|
91
109
|
|
|
92
|
-
let
|
|
110
|
+
let toProxyProto = (signal: Signal) => {
|
|
93
111
|
if (_instanceof(signal, Signal)) {
|
|
94
|
-
let
|
|
95
|
-
let
|
|
112
|
+
let proxy = new ProxyProto();
|
|
113
|
+
let $text: undefined | TextProto = _undefined;
|
|
114
|
+
let fn = (value: any) => {
|
|
115
|
+
// improve text content update performance
|
|
116
|
+
if (isString(value) || isBoolean(value) || isNumber(value)) {
|
|
117
|
+
if ($text) $text.content = `${value}`;
|
|
118
|
+
else proxy.layout = () => $text = $([ value ]).at(0) as TextProto;
|
|
119
|
+
if (!proxy.builded) proxy.build();
|
|
120
|
+
} else {
|
|
121
|
+
$text = _undefined;
|
|
122
|
+
proxy.layout = () => $([ value ]);
|
|
123
|
+
forEach(proxy.protos, proto => proto.removeNode())
|
|
124
|
+
// clean children nodes and dispose
|
|
125
|
+
proxy.clear(true);
|
|
126
|
+
if (proxy.builded) proxy.build();
|
|
127
|
+
proxy.node?.replaceWith(...proxy.toDOM());
|
|
128
|
+
}
|
|
129
|
+
}
|
|
96
130
|
signal.subscribe(fn);
|
|
97
|
-
|
|
131
|
+
proxy.listen('dispose', () => signal.unsubscribe(fn));
|
|
98
132
|
fn(signal.value);
|
|
99
|
-
return
|
|
133
|
+
return proxy;
|
|
100
134
|
}
|
|
101
135
|
}
|
|
102
136
|
|
|
103
|
-
$.process.text.add(
|
|
104
|
-
$.process.craft.add(
|
|
137
|
+
$.process.text.add(toProxyProto)
|
|
138
|
+
$.process.craft.add(toProxyProto)
|
|
105
139
|
$.process.attr.add((name, signal, proto) => {
|
|
106
140
|
if (_instanceof(signal, Signal)) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (isBoolean(value)) value && proto.attr(name, '');
|
|
112
|
-
else proto.attr(name, `${value}`)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
let setNodeAttr = () => proto.attr(name, signal.value as any);
|
|
117
|
-
signal.subscribe(setNodeAttr);
|
|
118
|
-
setNodeAttr();
|
|
119
|
-
proto.ondispose(() => signal.unsubscribe(setNodeAttr))
|
|
120
|
-
}
|
|
121
|
-
|
|
141
|
+
let setNodeAttr = () => proto.attr(name, signal.value as any);
|
|
142
|
+
signal.subscribe(setNodeAttr);
|
|
143
|
+
setNodeAttr();
|
|
144
|
+
proto.listen('dispose', () => signal.unsubscribe(setNodeAttr))
|
|
122
145
|
return true;
|
|
123
146
|
}
|
|
124
147
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _null, _Object_entries, forEach, isFunction, isString, isSymbol, isUndefined } from "@amateras/utils";
|
|
1
|
+
import { _instanceof, _null, _Object_entries, forEach, isFunction, isNull, isObject, isString, isSymbol, isUndefined } from "@amateras/utils";
|
|
2
2
|
import { ontrack, trackSet } from "#lib/track";
|
|
3
3
|
import { Proto, symbol_Signal } from "@amateras/core";
|
|
4
4
|
import type { SignalTypes } from "..";
|
|
@@ -19,15 +19,34 @@ export class Signal<T = any> extends Function {
|
|
|
19
19
|
super()
|
|
20
20
|
Proto.proto?.global.signals.add(this);
|
|
21
21
|
this._value = value;
|
|
22
|
+
// if value is Signal, use linked signal to prevent modify the original signal value
|
|
23
|
+
if (_instanceof(value, Signal)) this.link(value);
|
|
22
24
|
return new Proxy(this, {
|
|
23
25
|
apply: () => this._exec(),
|
|
24
|
-
get: (
|
|
26
|
+
get: (_, propName) => {
|
|
25
27
|
if (isSymbol(propName) || (isString(propName) && !propName.endsWith('$'))) return this[propName as keyof this];
|
|
26
|
-
|
|
28
|
+
// remove $ at last position of prop name
|
|
29
|
+
propName = propName.slice(0, -1);
|
|
27
30
|
if (!this.map) this.map = {};
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
const cachedSignal = this.map[propName];
|
|
32
|
+
if (cachedSignal) return cachedSignal;
|
|
33
|
+
else {
|
|
34
|
+
const signal = this.map[propName] ?? new Signal<any>(null);
|
|
35
|
+
this.map[propName] = signal;
|
|
36
|
+
// set signal value (before subscribe)
|
|
37
|
+
this.setPropValue(signal, propName);
|
|
38
|
+
signal.subscribe(newValue => {
|
|
39
|
+
// set member value to parent source object
|
|
40
|
+
if (isObject(this.value) && !isNull(this.value)) {
|
|
41
|
+
// avoid getter only member
|
|
42
|
+
if (Object.getOwnPropertyDescriptor(this.value, propName)?.writable) this.value[propName as keyof T] = newValue;
|
|
43
|
+
}
|
|
44
|
+
// emit parent signal
|
|
45
|
+
if (!isNull(this.value)) this.emit();
|
|
46
|
+
})
|
|
47
|
+
this.subscribe(() => this.setPropValue(signal, propName));
|
|
48
|
+
return signal;
|
|
49
|
+
}
|
|
31
50
|
}
|
|
32
51
|
});
|
|
33
52
|
}
|
|
@@ -36,6 +55,17 @@ export class Signal<T = any> extends Function {
|
|
|
36
55
|
if (ontrack) trackSet.add(this);
|
|
37
56
|
return this.value;
|
|
38
57
|
}
|
|
58
|
+
|
|
59
|
+
private setPropValue(signal: Signal, propName: string) {
|
|
60
|
+
if (isObject(this.value) && !isNull(this.value)) {
|
|
61
|
+
// parent signal value is object, set value from this object member
|
|
62
|
+
const value = this.value[propName as keyof T];
|
|
63
|
+
signal.set(value);
|
|
64
|
+
} else {
|
|
65
|
+
// parent signal value is not object, member signal value change to null quietly
|
|
66
|
+
signal._value = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
39
69
|
|
|
40
70
|
get value(): T {
|
|
41
71
|
if (this.linked) return this.linked.value;
|
|
@@ -54,16 +84,19 @@ export class Signal<T = any> extends Function {
|
|
|
54
84
|
}
|
|
55
85
|
|
|
56
86
|
set(resolver: T | ((oldValue: T) => T),) {
|
|
57
|
-
if
|
|
87
|
+
// if value is Signal, use linked signal to prevent modify the original signal value
|
|
88
|
+
if (_instanceof(resolver, Signal)) this.link(resolver);
|
|
58
89
|
else if (isFunction(resolver)) this.set(resolver(this.value));
|
|
59
90
|
else if (this.value !== resolver) {
|
|
60
91
|
this._value = resolver;
|
|
92
|
+
this.linked = _null;
|
|
61
93
|
this.emit();
|
|
62
94
|
}
|
|
63
95
|
}
|
|
64
96
|
|
|
65
97
|
modify(callback: (value: T) => void) {
|
|
66
98
|
callback(this.value);
|
|
99
|
+
this.linked?.emit();
|
|
67
100
|
this.emit();
|
|
68
101
|
}
|
|
69
102
|
|
|
@@ -16,7 +16,7 @@ export class Store<T = any, Args extends any[] = []> {
|
|
|
16
16
|
if (!root) throw `Store.create(): ${ERROR_MESSAGE}`;
|
|
17
17
|
const value = this.init(...args);
|
|
18
18
|
this.map.set(root, value);
|
|
19
|
-
root.
|
|
19
|
+
root.listen('dispose', () => this.map.delete(root));
|
|
20
20
|
return value;
|
|
21
21
|
}
|
|
22
22
|
|
package/packages/ui/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const check_svg = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-icon lucide-check"><path d="M20 6 9 17l-5-5"/></svg>`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const x_svg = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>`
|
package/packages/ui/src/index.ts
CHANGED
|
@@ -2,7 +2,6 @@ export * from "#lib/slideshowAnimations";
|
|
|
2
2
|
export * from "#structure/Slide";
|
|
3
3
|
export * from "#structure/Slideshow";
|
|
4
4
|
export * from "#structure/Radio";
|
|
5
|
-
export * from "#structure/TextBlock";
|
|
6
5
|
export * from "#structure/Accordion";
|
|
7
6
|
export * from "#structure/Waterfall";
|
|
8
7
|
export * from "#structure/WaterfallItem";
|
|
@@ -18,4 +17,12 @@ export * from "#structure/Button";
|
|
|
18
17
|
export * from "#structure/Badge";
|
|
19
18
|
export * from "#structure/Icon";
|
|
20
19
|
export * from "#structure/Card";
|
|
21
|
-
export * from "#structure/DescriptionList";
|
|
20
|
+
export * from "#structure/DescriptionList";
|
|
21
|
+
export * from "#structure/ContextMenu";
|
|
22
|
+
export * from "#structure/Input";
|
|
23
|
+
export * from "#structure/Field";
|
|
24
|
+
export * from "#structure/Switch";
|
|
25
|
+
export * from "#structure/Toggle";
|
|
26
|
+
export * from "#structure/Combobox/Combobox";
|
|
27
|
+
export * from "#structure/Combobox/ComboboxList";
|
|
28
|
+
export * from "#structure/Combobox/ComboboxChips";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CSSMap } from "./toCSS";
|
|
2
|
+
|
|
3
|
+
export const item_css = {
|
|
4
|
+
display: 'flex',
|
|
5
|
+
gap: 'calc(var(--spacing) * 1.25)',
|
|
6
|
+
boxSizing: 'border-box',
|
|
7
|
+
padding: 'calc(var(--spacing) * 2) calc(var(--spacing) * 1.25)',
|
|
8
|
+
borderRadius: 'var(--radius)',
|
|
9
|
+
fontSize: '0.875rem',
|
|
10
|
+
fontWeight: '500',
|
|
11
|
+
lineHeight: '1',
|
|
12
|
+
|
|
13
|
+
'&:hover, :not(:has(select-item:hover)) &[focus]': {
|
|
14
|
+
background: 'oklch(from var(--input) l c h / .1)'
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
'&[focus]': {
|
|
18
|
+
outline: 'none'
|
|
19
|
+
}
|
|
20
|
+
} satisfies CSSMap;
|
|
@@ -3,7 +3,7 @@ import { ElementProto } from "@amateras/core";
|
|
|
3
3
|
|
|
4
4
|
export interface BadgeProps {
|
|
5
5
|
variant?: 'primary' | 'outline' | 'secondary' | 'ghost' | 'destructive' | 'link' | string & {};
|
|
6
|
-
size?: 'base' | 'icon' | '
|
|
6
|
+
size?: 'base' | 'icon' | 'sm' | 'lg' | 'icon' | 'icon-xs' | 'icon-sm' | 'icon-lg' | string & {}
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export class Badge extends ElementProto<HTMLButtonElement> {
|
|
@@ -20,12 +20,14 @@ export class Badge extends ElementProto<HTMLButtonElement> {
|
|
|
20
20
|
padding: `0 calc(var(--spacing) * 2)`,
|
|
21
21
|
borderRadius: 'calc(var(--radius) * 2.6)',
|
|
22
22
|
height: 'calc(var(--spacing) * 5)',
|
|
23
|
+
lineHeight: 'var(--text-xs)',
|
|
23
24
|
transition: '0.2s all ease',
|
|
24
25
|
fontSize: 'var(--text-xs)',
|
|
25
26
|
fontWeight: 'var(--font-weight-medium)',
|
|
26
27
|
fontFamily: 'inherit',
|
|
27
28
|
outline: '0.1rem solid oklch(from var(--border) l c h / 0)',
|
|
28
29
|
whiteSpace: 'nowrap',
|
|
30
|
+
gap: `var(--spacing)`,
|
|
29
31
|
|
|
30
32
|
border: '1px solid oklch(from var(--input) l c h / .2)',
|
|
31
33
|
background: 'oklch(from var(--input) l c h / .025)',
|
|
@@ -83,6 +85,13 @@ export class Badge extends ElementProto<HTMLButtonElement> {
|
|
|
83
85
|
}
|
|
84
86
|
},
|
|
85
87
|
|
|
88
|
+
'&[size="sm"]': {
|
|
89
|
+
padding: '0 calc(var(--spacing) * 1)',
|
|
90
|
+
fontSize: 'var(--text-xs2)',
|
|
91
|
+
lineHeight: 'var(--text-xs2)',
|
|
92
|
+
height: 'calc(var(--spacing) * 4)'
|
|
93
|
+
},
|
|
94
|
+
|
|
86
95
|
'a[disabled] &': {
|
|
87
96
|
opacity: '.5'
|
|
88
97
|
}
|
|
@@ -1,29 +1,33 @@
|
|
|
1
|
+
import { pointerHoverMediaQuery } from "#lib/hover";
|
|
1
2
|
import { toCSS } from "#lib/toCSS";
|
|
2
3
|
import { ElementProto } from "@amateras/core";
|
|
3
4
|
|
|
4
5
|
export interface ButtonProps {
|
|
5
|
-
variant?: 'primary' | 'outline' | 'secondary' | 'ghost' | 'destructive' | 'link' | string & {}
|
|
6
|
-
size?: 'base' | 'icon' | 'xs' | 'sm' | 'lg' | 'icon' | 'icon-xs' | 'icon-sm' | 'icon-lg' | string & {}
|
|
6
|
+
variant?: OrSignal<'primary' | 'outline' | 'secondary' | 'ghost' | 'destructive' | 'link' | string & {}>;
|
|
7
|
+
size?: OrSignal<'base' | 'icon' | 'xs' | 'sm' | 'lg' | 'icon' | 'icon-xs' | 'icon-sm' | 'icon-lg' | string & {}>;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export class Button extends ElementProto<HTMLButtonElement> {
|
|
10
11
|
static tagname = 'button';
|
|
11
|
-
constructor(props: $.Props<ButtonProps>, layout?: $.Layout<Button>) {
|
|
12
|
-
super(
|
|
12
|
+
constructor(props: $.Props<ButtonProps, HTMLButtonElement>, layout?: $.Layout<Button>) {
|
|
13
|
+
super('button', {ui: 'button', ...props}, layout)
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
static {
|
|
16
|
-
$.style(this, toCSS(
|
|
17
|
+
$.style(this, toCSS('button[ui="button"]', {
|
|
17
18
|
display: 'inline-flex',
|
|
18
19
|
placeContent: 'center',
|
|
19
20
|
placeItems: 'center',
|
|
20
21
|
padding: `0 calc(var(--spacing) * 2.5)`,
|
|
21
22
|
borderRadius: 'var(--radius)',
|
|
22
23
|
height: 'calc(var(--spacing) * 8)',
|
|
24
|
+
lineHeight: '1rem',
|
|
23
25
|
transition: '0.2s all ease',
|
|
24
26
|
fontWeight: 'var(--font-weight-medium)',
|
|
25
27
|
fontFamily: 'inherit',
|
|
26
28
|
outline: '0.1rem solid oklch(from var(--border) l c h / 0)',
|
|
29
|
+
userSelect: 'none',
|
|
30
|
+
gap: 'calc(var(--spacing) * 2.5)',
|
|
27
31
|
|
|
28
32
|
border: '1px solid oklch(from var(--input) l c h / .2)',
|
|
29
33
|
background: 'oklch(from var(--input) l c h / .025)',
|
|
@@ -33,56 +37,75 @@ export class Button extends ElementProto<HTMLButtonElement> {
|
|
|
33
37
|
outline: '0.1rem solid var(--border)'
|
|
34
38
|
},
|
|
35
39
|
|
|
36
|
-
'&:active': {
|
|
40
|
+
'&:not([disabled]):active': {
|
|
37
41
|
translate: '0 0.125rem'
|
|
38
42
|
},
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
[pointerHoverMediaQuery]: {
|
|
45
|
+
'&:not([disabled]):hover': {
|
|
46
|
+
background: 'oklch(from var(--input) l c h / .1)',
|
|
47
|
+
},
|
|
43
48
|
},
|
|
44
49
|
|
|
45
50
|
'&[variant="primary"]': {
|
|
46
51
|
border: 'none',
|
|
47
52
|
color: 'oklch(from var(--primary-fg) l c h)',
|
|
48
|
-
background: 'var(--primary-bg)'
|
|
53
|
+
background: 'var(--primary-bg)',
|
|
54
|
+
|
|
55
|
+
[pointerHoverMediaQuery]: {
|
|
56
|
+
'&:not([disabled]):hover': {
|
|
57
|
+
background: 'oklch(from var(--primary-bg) l c h / .8)',
|
|
58
|
+
}
|
|
59
|
+
}
|
|
49
60
|
},
|
|
50
61
|
|
|
51
62
|
'&[variant="secondary"]': {
|
|
52
63
|
border: 'none',
|
|
53
64
|
color: 'oklch(from var(--secondary-fg) l c h)',
|
|
54
65
|
background: 'var(--secondary-bg)',
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
|
|
67
|
+
[pointerHoverMediaQuery]: {
|
|
68
|
+
'&:not([disabled]):hover': {
|
|
69
|
+
background: 'oklch(from var(--secondary-bg) l c h / .8)'
|
|
70
|
+
}
|
|
71
|
+
},
|
|
58
72
|
},
|
|
59
73
|
|
|
60
74
|
'&[variant="destructive"]': {
|
|
61
75
|
border: 'none',
|
|
62
76
|
color: 'oklch(from var(--destructive-fg) l c h)',
|
|
63
77
|
background: 'oklch(from var(--destructive-bg) l c h / .3)',
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
78
|
+
|
|
79
|
+
[pointerHoverMediaQuery]: {
|
|
80
|
+
'&:not([disabled]):hover': {
|
|
81
|
+
background: 'oklch(from var(--destructive-bg) l c h / .5)'
|
|
82
|
+
}
|
|
83
|
+
},
|
|
67
84
|
},
|
|
68
85
|
|
|
69
86
|
'&[variant="ghost"]': {
|
|
70
87
|
border: 'none',
|
|
71
88
|
color: 'oklch(from var(--fg) l c h)',
|
|
72
89
|
background: 'oklch(from var(--input) l c h / 0)',
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
|
|
91
|
+
[pointerHoverMediaQuery]: {
|
|
92
|
+
'&:not([disabled]):hover': {
|
|
93
|
+
background: 'oklch(from var(--input) l c h / .1)'
|
|
94
|
+
}
|
|
95
|
+
},
|
|
76
96
|
},
|
|
77
97
|
|
|
78
98
|
'&[variant="link"]': {
|
|
79
99
|
border: 'none',
|
|
80
100
|
color: 'oklch(from var(--fg) l c h)',
|
|
81
101
|
background: 'oklch(from var(--input) l c h / 0)',
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
102
|
+
|
|
103
|
+
[pointerHoverMediaQuery]: {
|
|
104
|
+
'&:not([disabled]):hover': {
|
|
105
|
+
textDecoration: 'underline',
|
|
106
|
+
textUnderlineOffset: '0.2rem'
|
|
107
|
+
}
|
|
108
|
+
},
|
|
86
109
|
},
|
|
87
110
|
|
|
88
111
|
'&[size="icon"]': {
|
|
@@ -92,13 +115,15 @@ export class Button extends ElementProto<HTMLButtonElement> {
|
|
|
92
115
|
|
|
93
116
|
'&[size="xs"]': {
|
|
94
117
|
padding: 'calc(var(--spacing) * 2)',
|
|
95
|
-
fontSize: 'var(--
|
|
96
|
-
|
|
118
|
+
fontSize: 'var(--text-xs)',
|
|
119
|
+
lineHeight: 'var(--text-xs)',
|
|
120
|
+
height: 'calc(var(--spacing) * 6)',
|
|
97
121
|
},
|
|
98
122
|
|
|
99
123
|
'&[size="icon-xs"]': {
|
|
100
124
|
width: 'calc(var(--spacing) * 6)',
|
|
101
125
|
height: 'calc(var(--spacing) * 6)',
|
|
126
|
+
padding: '0',
|
|
102
127
|
|
|
103
128
|
'svg': {
|
|
104
129
|
width: 'calc(var(--spacing) * 3)',
|
|
@@ -112,7 +137,8 @@ export class Button extends ElementProto<HTMLButtonElement> {
|
|
|
112
137
|
|
|
113
138
|
'&[size="icon-sm"]': {
|
|
114
139
|
width: 'calc(var(--spacing) * 7)',
|
|
115
|
-
height: 'calc(var(--spacing) * 7)'
|
|
140
|
+
height: 'calc(var(--spacing) * 7)',
|
|
141
|
+
padding: '0',
|
|
116
142
|
},
|
|
117
143
|
|
|
118
144
|
'&[size="lg"]': {
|
|
@@ -121,7 +147,8 @@ export class Button extends ElementProto<HTMLButtonElement> {
|
|
|
121
147
|
|
|
122
148
|
'&[size="icon-lg"]': {
|
|
123
149
|
width: 'calc(var(--spacing) * 9)',
|
|
124
|
-
height: 'calc(var(--spacing) * 9)'
|
|
150
|
+
height: 'calc(var(--spacing) * 9)',
|
|
151
|
+
padding: '0',
|
|
125
152
|
},
|
|
126
153
|
|
|
127
154
|
'&[disabled]': {
|
|
@@ -32,12 +32,10 @@ export class CardHeader extends ElementProto {
|
|
|
32
32
|
|
|
33
33
|
static {
|
|
34
34
|
$.style(this, toCSS(this.tagname, {
|
|
35
|
-
display: '
|
|
35
|
+
display: 'flex',
|
|
36
36
|
width: '100%',
|
|
37
|
-
|
|
38
|
-
// gridTemplateColumns: '1fr auto',
|
|
37
|
+
flexDirection: 'column',
|
|
39
38
|
gap: 'var(--spacing)',
|
|
40
|
-
container: 'card-header / inline-size ',
|
|
41
39
|
|
|
42
40
|
paddingInline: 'calc(var(--spacing) * 4)',
|
|
43
41
|
}))
|
|
@@ -52,6 +50,7 @@ export class CardContent extends ElementProto {
|
|
|
52
50
|
|
|
53
51
|
static {
|
|
54
52
|
$.style(this, toCSS(this.tagname, {
|
|
53
|
+
display: 'block',
|
|
55
54
|
paddingInline: 'calc(var(--spacing) * 4)',
|
|
56
55
|
}))
|
|
57
56
|
}
|