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.
Files changed (89) hide show
  1. package/README.md +39 -38
  2. package/build/core.js +1 -1
  3. package/build/css-keyframes.js +1 -0
  4. package/build/css-property.js +1 -0
  5. package/build/css-variable.js +1 -0
  6. package/build/for.js +1 -1
  7. package/build/i18n.js +1 -1
  8. package/build/if.js +1 -1
  9. package/build/import-map.js +1 -1
  10. package/build/match.js +1 -1
  11. package/build/meta.js +1 -1
  12. package/build/prefetch.js +1 -1
  13. package/build/router.js +1 -1
  14. package/build/signal.js +1 -1
  15. package/build/store.js +1 -1
  16. package/build/ui.js +1 -1
  17. package/build/utils.js +1 -1
  18. package/build/widget.js +1 -1
  19. package/package.json +3 -2
  20. package/packages/core/src/index.ts +86 -31
  21. package/packages/core/src/lib/hmr.ts +4 -4
  22. package/packages/core/src/structure/ElementProto.ts +33 -11
  23. package/packages/core/src/structure/GlobalState.ts +13 -4
  24. package/packages/core/src/structure/NodeProto.ts +2 -4
  25. package/packages/core/src/structure/Proto.ts +37 -23
  26. package/packages/core/src/structure/TextProto.ts +1 -2
  27. package/packages/css/README.md +18 -15
  28. package/packages/css/src/ext/property.ts +2 -3
  29. package/packages/css/src/index.ts +1 -1
  30. package/packages/css/src/structure/$CSSProperty.ts +4 -0
  31. package/packages/css/src/structure/$CSSVariable.ts +1 -1
  32. package/packages/css/src/types.ts +5 -0
  33. package/packages/for/src/global.ts +12 -3
  34. package/packages/for/src/structure/For.ts +5 -3
  35. package/packages/i18n/README.md +16 -24
  36. package/packages/i18n/src/index.ts +26 -5
  37. package/packages/i18n/src/structure/I18n.ts +2 -4
  38. package/packages/i18n/src/structure/I18nSession.ts +4 -2
  39. package/packages/i18n/src/structure/I18nTranslation.ts +15 -26
  40. package/packages/idb/src/structure/$IDBStore.ts +2 -2
  41. package/packages/if/src/global.ts +15 -4
  42. package/packages/if/src/index.ts +18 -8
  43. package/packages/if/src/structure/Condition.ts +16 -13
  44. package/packages/if/src/structure/ConditionStatement.ts +9 -9
  45. package/packages/match/src/global.ts +9 -3
  46. package/packages/match/src/structure/Match.ts +1 -1
  47. package/packages/meta/src/index.ts +4 -5
  48. package/packages/prefetch/src/index.ts +30 -9
  49. package/packages/router/src/global.ts +17 -4
  50. package/packages/router/src/index.ts +25 -18
  51. package/packages/router/src/structure/Route.ts +2 -1
  52. package/packages/router/src/structure/RouteNode.ts +8 -6
  53. package/packages/router/src/structure/RouteSlot.ts +15 -2
  54. package/packages/router/src/structure/Router.ts +28 -19
  55. package/packages/router/src/structure/RouterConstructor.ts +5 -5
  56. package/packages/router/src/types.ts +2 -2
  57. package/packages/signal/README.md +28 -48
  58. package/packages/signal/src/index.ts +61 -38
  59. package/packages/signal/src/structure/Signal.ts +40 -7
  60. package/packages/store/src/structure/Store.ts +1 -1
  61. package/packages/ui/package.json +2 -1
  62. package/packages/ui/src/icon/check.svg.ts +1 -0
  63. package/packages/ui/src/icon/x.svg.ts +1 -0
  64. package/packages/ui/src/index.ts +9 -2
  65. package/packages/ui/src/lib/combobox_style.ts +20 -0
  66. package/packages/ui/src/lib/hover.ts +2 -0
  67. package/packages/ui/src/structure/Badge.ts +10 -1
  68. package/packages/ui/src/structure/Button.ts +54 -27
  69. package/packages/ui/src/structure/Card.ts +3 -4
  70. package/packages/ui/src/structure/Combobox/Combobox.ts +312 -0
  71. package/packages/ui/src/structure/Combobox/ComboboxChips.ts +178 -0
  72. package/packages/ui/src/structure/Combobox/ComboboxList.ts +209 -0
  73. package/packages/ui/src/structure/ContextMenu.ts +89 -0
  74. package/packages/ui/src/structure/Field.ts +109 -0
  75. package/packages/ui/src/structure/Input.ts +29 -0
  76. package/packages/ui/src/structure/Select/Select.ts +18 -8
  77. package/packages/ui/src/structure/Select/SelectContent.ts +6 -1
  78. package/packages/ui/src/structure/Select/SelectItem.ts +2 -1
  79. package/packages/ui/src/structure/Slideshow.ts +2 -2
  80. package/packages/ui/src/structure/Switch.ts +45 -0
  81. package/packages/ui/src/structure/Tabs.ts +3 -3
  82. package/packages/ui/src/structure/Toggle.ts +155 -0
  83. package/packages/ui/src/structure/Waterfall.ts +1 -1
  84. package/packages/ui/src/structure/WaterfallItem.ts +1 -1
  85. package/packages/utils/src/lib/utils.ts +30 -8
  86. package/packages/utils/src/structure/UID.ts +1 -1
  87. package/packages/widget/src/index.ts +29 -9
  88. package/packages/widget/src/structure/Widget.ts +7 -3
  89. 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, isIncluded, forEach, isBoolean, _null } from "@amateras/utils";
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): Signal<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 OrSignal<infer K> ? K : T) => void): T;
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> = [T] extends [object]
27
- ? SignalObject<T>
28
- : Signal<T>
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
- compute.exec = () => compute.set(callback(untrack));
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 toTextProto = (signal: Signal) => {
110
+ let toProxyProto = (signal: Signal) => {
93
111
  if (_instanceof(signal, Signal)) {
94
- let proto = new TextProto(`${signal}`);
95
- let fn = (value: any) => proto.content = `${value}`;
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
- proto.ondispose(() => signal.unsubscribe(fn));
131
+ proxy.listen('dispose', () => signal.unsubscribe(fn));
98
132
  fn(signal.value);
99
- return proto;
133
+ return proxy;
100
134
  }
101
135
  }
102
136
 
103
- $.process.text.add(toTextProto)
104
- $.process.craft.add(toTextProto)
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
- if (proto.tagname === 'input') {
108
- if (isIncluded(name, ['value', 'checked'] as const)) {
109
- proto.on('input', e => signal.set((e.currentTarget as HTMLInputElement)[name]));
110
- let value = signal.value;
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: (target, propName) => {
26
+ get: (_, propName) => {
25
27
  if (isSymbol(propName) || (isString(propName) && !propName.endsWith('$'))) return this[propName as keyof this];
26
- const value = this.value[propName.slice(0, -1) as keyof T];
28
+ // remove $ at last position of prop name
29
+ propName = propName.slice(0, -1);
27
30
  if (!this.map) this.map = {};
28
- const signal = this.map[propName] ?? new Signal(value);
29
- this.map[propName] = signal;
30
- return signal;
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 (this.linked) this.linked.set(resolver);
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.ondispose(() => this.map.delete(root));
19
+ root.listen('dispose', () => this.map.delete(root));
20
20
  return value;
21
21
  }
22
22
 
@@ -11,5 +11,6 @@
11
11
  },
12
12
  "exports": {
13
13
  ".": "./src/index.ts"
14
- }
14
+ },
15
+ "sideEffects": false
15
16
  }
@@ -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>`
@@ -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;
@@ -0,0 +1,2 @@
1
+
2
+ export const pointerHoverMediaQuery = '@media (hover: hover) and (pointer: fine)'
@@ -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' | 'xs' | 'sm' | 'lg' | 'icon' | 'icon-xs' | 'icon-sm' | 'icon-lg' | string & {}
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(Button.tagname, props, layout)
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(this.tagname, {
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
- '&:not([disabled]):hover': {
41
- background: 'oklch(from var(--input) l c h / .1)',
42
- color: 'oklch(from var(--fg) l c h / 1)',
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
- '&:not([disabled]):hover': {
56
- background: 'oklch(from var(--secondary-bg) l c h / .8)'
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
- '&:not([disabled]):hover': {
65
- background: 'oklch(from var(--destructive-bg) l c h / .5)'
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
- '&:not([disabled]):hover': {
74
- background: 'oklch(from var(--input) l c h / .1)'
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
- '&:not([disabled]):hover': {
83
- textDecoration: 'underline',
84
- textUnderlineOffset: '0.2rem'
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(--text_xs)',
96
- height: 'calc(var(--spacing) * 6)'
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: 'grid',
35
+ display: 'flex',
36
36
  width: '100%',
37
- gridTemplateRows: 'auto auto',
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
  }