@threadlabs/looma 0.12.5 → 0.12.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.12.5",
3
+ "version": "0.12.6",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -16,6 +16,19 @@
16
16
  text-transform: uppercase;
17
17
  }
18
18
 
19
+ :scope[data-ui-avatar-state~="size=sm"] {
20
+ inline-size: 1.75rem;
21
+ block-size: 1.75rem;
22
+ font-size: var(--ui-font-size-xs);
23
+ }
24
+
25
+ /* An outline, not a dot: the avatar clips its content to the circle, and an outline is drawn
26
+ outside the box, so the ring survives the clip and the overlap in an Avatar Group. */
27
+ :scope[data-ui-avatar-state~="active"] {
28
+ outline: 2px solid var(--ui-avatar-active-ring, var(--ui-success));
29
+ outline-offset: 1px;
30
+ }
31
+
19
32
  .fallback {
20
33
  grid-area: 1 / 1;
21
34
  display: inline-flex;
@@ -48,7 +61,10 @@
48
61
  }
49
62
  }
50
63
  @scope ([data-component~="ui-avatar"]) to ([data-component]) {
51
- .image,
64
+ /* An outline, not a dot: the avatar clips its content to the circle, and an outline is drawn
65
+ outside the box, so the ring survives the clip and the overlap in an Avatar Group. */
66
+
67
+ .image,
52
68
  :where([data-slotted], [data-slotted] *):is(img) {
53
69
  grid-area: 1 / 1;
54
70
  inline-size: 100%;
@@ -6,9 +6,11 @@ export interface UiAvatarElement extends HTMLSpanElement {
6
6
  removeEventListener<K extends keyof UiAvatarEventMap>(type: K, listener: (this: UiAvatarElement, event: UiAvatarEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
7
7
  }
8
8
  export interface UiAvatarProps {
9
+ active?: boolean | null;
9
10
  alt?: string | null;
10
11
  fallback?: string | null;
11
12
  name?: string | null;
13
+ size?: "sm" | "md" | null;
12
14
  src?: string | null;
13
15
  attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
14
16
  children?: readonly (string | Node)[];
@@ -3,7 +3,7 @@ import { manageComponentLifecycle } from "@nextwebwg/html-next/runtime";
3
3
  import * as controller from "../components/ui-avatar/ui-avatar.js";
4
4
  import "../styles/ui-avatar.css";
5
5
 
6
- const definition = {...{"contract":{"tag":"ui-avatar","props":{"alt":{"type":"string","required":false,"target":{"attribute":"alt"},"default":""},"fallback":{"type":"string","required":false,"target":{"attribute":"fallback"},"default":""},"name":{"type":"string","required":false,"target":{"attribute":"name"},"default":""},"src":{"type":"string","required":false,"target":{"attribute":"src"}}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"},{"kind":"element","name":"img","attributes":[{"kind":"literal","name":"class","value":"image"},{"kind":"attribute","name":"src","expression":"src","expressionPlan":{"source":"src","ast":{"kind":"id","name":"src"},"dependencies":["src"]}},{"kind":"literal","name":"alt","value":""},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"attribute","name":"hidden","expression":"hasAuthoredImage or not hasImage","expressionPlan":{"source":"hasAuthoredImage or not hasImage","ast":{"kind":"binary","op":"or","left":{"kind":"id","name":"hasAuthoredImage"},"right":{"kind":"unary","op":"not","operand":{"kind":"id","name":"hasImage"}}},"dependencies":["hasAuthoredImage","hasImage"]}}],"children":[],"ref":"image"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"fallback"},{"kind":"attribute","name":"aria-hidden","expression":"hasImage","expressionPlan":{"source":"hasImage","ast":{"kind":"id","name":"hasImage"},"dependencies":["hasImage"]}},{"kind":"attribute","name":"hidden","expression":"hasImage","expressionPlan":{"source":"hasImage","ast":{"kind":"id","name":"hasImage"},"dependencies":["hasImage"]}},{"kind":"directive","name":"value","expression":"initials","expressionPlan":{"source":"initials","ast":{"kind":"id","name":"initials"},"dependencies":["initials"]}}],"children":[]}]},"declarations":[{"kind":"state","name":"hasImage","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"hasAuthoredImage","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"initials","expression":{"source":"'?'","ast":{"kind":"literal","value":"?"},"dependencies":[]}}],"root":{"kind":"native","element":"span","choices":["span"]}},source:{file:import.meta.url},css:""};
6
+ const definition = {...{"contract":{"tag":"ui-avatar","props":{"active":{"type":"boolean","required":false,"target":{"attribute":"active"},"default":false},"alt":{"type":"string","required":false,"target":{"attribute":"alt"},"default":""},"fallback":{"type":"string","required":false,"target":{"attribute":"fallback"},"default":""},"name":{"type":"string","required":false,"target":{"attribute":"name"},"default":""},"size":{"type":{"enum":["sm","md"]},"required":false,"target":{"attribute":"size"},"default":"md"},"src":{"type":"string","required":false,"target":{"attribute":"src"}}}},"template":{"kind":"element","name":"span","attributes":[],"children":[{"kind":"slot"},{"kind":"element","name":"img","attributes":[{"kind":"literal","name":"class","value":"image"},{"kind":"attribute","name":"src","expression":"src","expressionPlan":{"source":"src","ast":{"kind":"id","name":"src"},"dependencies":["src"]}},{"kind":"literal","name":"alt","value":""},{"kind":"literal","name":"aria-hidden","value":"true"},{"kind":"attribute","name":"hidden","expression":"hasAuthoredImage or not hasImage","expressionPlan":{"source":"hasAuthoredImage or not hasImage","ast":{"kind":"binary","op":"or","left":{"kind":"id","name":"hasAuthoredImage"},"right":{"kind":"unary","op":"not","operand":{"kind":"id","name":"hasImage"}}},"dependencies":["hasAuthoredImage","hasImage"]}}],"children":[],"ref":"image"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"fallback"},{"kind":"attribute","name":"aria-hidden","expression":"hasImage","expressionPlan":{"source":"hasImage","ast":{"kind":"id","name":"hasImage"},"dependencies":["hasImage"]}},{"kind":"attribute","name":"hidden","expression":"hasImage","expressionPlan":{"source":"hasImage","ast":{"kind":"id","name":"hasImage"},"dependencies":["hasImage"]}},{"kind":"directive","name":"value","expression":"initials","expressionPlan":{"source":"initials","ast":{"kind":"id","name":"initials"},"dependencies":["initials"]}}],"children":[]}]},"declarations":[{"kind":"state","name":"hasImage","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"hasAuthoredImage","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"initials","expression":{"source":"'?'","ast":{"kind":"literal","value":"?"},"dependencies":[]}}],"root":{"kind":"native","element":"span","choices":["span"]}},source:{file:import.meta.url},css:""};
7
7
 
8
8
  export function createUiAvatar(options = {}) {
9
9
  const { attributes = {}, children = [], slots = {}, as, ...componentProps } = options;
package/vue/UiAvatar.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  type __VLS_Props = {
2
+ active?: boolean;
2
3
  alt?: string;
3
4
  fallback?: string;
4
5
  name?: string;
6
+ size?: 'sm' | 'md';
5
7
  src?: string;
6
8
  };
7
9
  declare var __VLS_1: {};
@@ -10,8 +12,10 @@ type __VLS_Slots = {} & {
10
12
  };
11
13
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
12
14
  name: string;
15
+ active: boolean;
13
16
  alt: string;
14
17
  fallback: string;
18
+ size: "sm" | "md";
15
19
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
20
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
17
21
  declare const _default: typeof __VLS_export;
package/vue/UiAvatar.vue CHANGED
@@ -1,6 +1,6 @@
1
1
  <!-- Generated by HTML Next 1.0.0-alpha.5 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
- import { ref, useTemplateRef } from 'vue'
3
+ import { computed, ref, useTemplateRef } from 'vue'
4
4
  import * as controllerModule from '../components/ui-avatar/ui-avatar.js'
5
5
  import { createDispatch, useComponentHost } from './host'
6
6
 
@@ -8,15 +8,19 @@ defineOptions({ inheritAttrs: false })
8
8
 
9
9
  const props = withDefaults(
10
10
  defineProps<{
11
+ active?: boolean
11
12
  alt?: string
12
13
  fallback?: string
13
14
  name?: string
15
+ size?: 'sm' | 'md'
14
16
  src?: string
15
17
  }>(),
16
18
  {
19
+ active: false,
17
20
  alt: '',
18
21
  fallback: '',
19
22
  name: '',
23
+ size: 'md',
20
24
  },
21
25
  )
22
26
 
@@ -26,6 +30,14 @@ const hasImage = ref(false)
26
30
  const hasAuthoredImage = ref(false)
27
31
  const initials = ref('?')
28
32
 
33
+ /** The values the styles' :host-state() rules test. */
34
+ const hostState = computed(() =>
35
+ [
36
+ props.size && `size size=${props.size}`,
37
+ props.active && 'active',
38
+ ].filter(Boolean).join(' ')
39
+ )
40
+
29
41
  const dispatch = createDispatch(root)
30
42
 
31
43
  useComponentHost(controllerModule.default, {
@@ -38,7 +50,12 @@ useComponentHost(controllerModule.default, {
38
50
  </script>
39
51
 
40
52
  <template>
41
- <span data-component="ui-avatar" v-bind="$attrs" ref="root"><slot />
53
+ <span
54
+ data-component="ui-avatar"
55
+ v-bind="$attrs"
56
+ :data-ui-avatar-state="hostState || undefined"
57
+ ref="root"
58
+ ><slot />
42
59
  <img
43
60
  class="image"
44
61
  alt=""
@@ -67,6 +84,19 @@ useComponentHost(controllerModule.default, {
67
84
  text-transform: uppercase;
68
85
  }
69
86
 
87
+ [data-component~="ui-avatar"][data-ui-avatar-state~="size=sm"] {
88
+ inline-size: 1.75rem;
89
+ block-size: 1.75rem;
90
+ font-size: var(--ui-font-size-xs);
91
+ }
92
+
93
+ /* An outline, not a dot: the avatar clips its content to the circle, and an outline is drawn
94
+ outside the box, so the ring survives the clip and the overlap in an Avatar Group. */
95
+ [data-component~="ui-avatar"][data-ui-avatar-state~="active"] {
96
+ outline: 2px solid var(--ui-avatar-active-ring, var(--ui-success));
97
+ outline-offset: 1px;
98
+ }
99
+
70
100
  .image,
71
101
  :slotted(img) {
72
102
  grid-area: 1 / 1;
package/vue/UiButton.d.ts CHANGED
@@ -17,12 +17,12 @@ type __VLS_Slots = {} & {
17
17
  };
18
18
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
19
19
  type: "button" | "submit" | "reset";
20
+ size: "sm" | "md" | "lg";
20
21
  tone: "accent" | "neutral" | "danger" | "success" | "warning" | "info";
21
22
  variant: "outline" | "solid" | "danger" | "ghost" | "link";
22
23
  as: "button" | "a";
23
24
  align: "center" | "start";
24
25
  disabled: boolean;
25
- size: "sm" | "md" | "lg";
26
26
  stretch: boolean;
27
27
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
28
28
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -236,8 +236,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
236
236
  }>, {
237
237
  label: string;
238
238
  name: string;
239
- disabled: boolean;
240
239
  size: "sm" | "md";
240
+ disabled: boolean;
241
241
  required: boolean;
242
242
  allowCreate: boolean;
243
243
  allowFreeText: boolean;
@@ -11,10 +11,10 @@ type __VLS_Slots = {} & {
11
11
  default?: (props: typeof __VLS_1) => any;
12
12
  };
13
13
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
14
+ size: "sm" | "md" | "lg";
14
15
  variant: "ghost" | "outline" | "solid";
15
16
  round: boolean;
16
17
  disabled: boolean;
17
- size: "sm" | "md" | "lg";
18
18
  anticipatory: boolean;
19
19
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
20
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
package/vue/UiText.d.ts CHANGED
@@ -12,11 +12,11 @@ type __VLS_Slots = {} & {
12
12
  default?: (props: typeof __VLS_8) => any;
13
13
  };
14
14
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
15
+ size: "inherit" | "xs" | "sm" | "md" | "lg";
15
16
  tone: "default" | "secondary" | "muted" | "accent" | "danger" | "success";
16
17
  variant: "body" | "eyebrow" | "code";
17
18
  as: "p" | "span" | "div" | "small" | "strong" | "label";
18
19
  align: "start" | "center";
19
- size: "inherit" | "xs" | "sm" | "md" | "lg";
20
20
  truncate: boolean;
21
21
  weight: "inherit" | "normal" | "medium" | "semibold";
22
22
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -1,19 +1,25 @@
1
1
  import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper.js";
2
2
  import { n as useComponentHost, t as createDispatch } from "./host.js";
3
- import { createElementBlock, createElementVNode, defineComponent, mergeProps, openBlock, ref, renderSlot, toDisplayString, useTemplateRef } from "vue";
3
+ import { computed, createElementBlock, createElementVNode, defineComponent, mergeProps, openBlock, ref, renderSlot, toDisplayString, useTemplateRef } from "vue";
4
4
  import * as controllerModule from "@threadlabs/looma/components/ui-avatar/ui-avatar.js";
5
5
  //#region .build/vue/UiAvatar.vue?vue&type=script&setup=true&lang.ts
6
- var _hoisted_1 = ["src", "hidden"];
7
- var _hoisted_2 = ["aria-hidden", "hidden"];
6
+ var _hoisted_1 = ["data-ui-avatar-state"];
7
+ var _hoisted_2 = ["src", "hidden"];
8
+ var _hoisted_3 = ["aria-hidden", "hidden"];
8
9
  //#endregion
9
10
  //#region .build/vue/UiAvatar.vue
10
11
  var UiAvatar_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
11
12
  inheritAttrs: false,
12
13
  __name: "UiAvatar",
13
14
  props: {
15
+ active: {
16
+ type: Boolean,
17
+ default: false
18
+ },
14
19
  alt: { default: "" },
15
20
  fallback: { default: "" },
16
21
  name: { default: "" },
22
+ size: { default: "md" },
17
23
  src: {}
18
24
  },
19
25
  setup(__props) {
@@ -23,6 +29,8 @@ var UiAvatar_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PUR
23
29
  const hasImage = ref(false);
24
30
  const hasAuthoredImage = ref(false);
25
31
  const initials = ref("?");
32
+ /** The values the styles' :host-state() rules test. */
33
+ const hostState = computed(() => [props.size && `size size=${props.size}`, props.active && "active"].filter(Boolean).join(" "));
26
34
  const dispatch = createDispatch(root);
27
35
  useComponentHost(controllerModule.default, {
28
36
  root,
@@ -37,6 +45,7 @@ var UiAvatar_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PUR
37
45
  });
38
46
  return (_ctx, _cache) => {
39
47
  return openBlock(), createElementBlock("span", mergeProps({ "data-component": "ui-avatar" }, _ctx.$attrs, {
48
+ "data-ui-avatar-state": hostState.value || void 0,
40
49
  ref_key: "root",
41
50
  ref: root
42
51
  }), [
@@ -48,15 +57,15 @@ var UiAvatar_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PUR
48
57
  src: __props.src,
49
58
  hidden: hasAuthoredImage.value || !hasImage.value,
50
59
  ref: "image"
51
- }, null, 8, _hoisted_1),
60
+ }, null, 8, _hoisted_2),
52
61
  createElementVNode("span", {
53
62
  class: "fallback",
54
63
  "aria-hidden": hasImage.value,
55
64
  hidden: hasImage.value
56
- }, toDisplayString(initials.value), 9, _hoisted_2)
57
- ], 16);
65
+ }, toDisplayString(initials.value), 9, _hoisted_3)
66
+ ], 16, _hoisted_1);
58
67
  };
59
68
  }
60
- }), [["__scopeId", "data-v-ebb1bbbb"]]);
69
+ }), [["__scopeId", "data-v-a5e0e48e"]]);
61
70
  //#endregion
62
71
  export { UiAvatar_default as t };
@@ -68,7 +68,7 @@
68
68
  display: none;
69
69
  }
70
70
 
71
- [data-component~="ui-avatar"][data-v-ebb1bbbb] {
71
+ [data-component~="ui-avatar"][data-v-a5e0e48e] {
72
72
  display: inline-grid;
73
73
  place-items: center;
74
74
  overflow: hidden;
@@ -83,13 +83,25 @@
83
83
  font-weight: 600;
84
84
  text-transform: uppercase;
85
85
  }
86
- .image[data-v-ebb1bbbb],img[data-v-ebb1bbbb-s] {
86
+ [data-component~="ui-avatar"][data-ui-avatar-state~="size=sm"][data-v-a5e0e48e] {
87
+ inline-size: 1.75rem;
88
+ block-size: 1.75rem;
89
+ font-size: var(--ui-font-size-xs);
90
+ }
91
+
92
+ /* An outline, not a dot: the avatar clips its content to the circle, and an outline is drawn
93
+ outside the box, so the ring survives the clip and the overlap in an Avatar Group. */
94
+ [data-component~="ui-avatar"][data-ui-avatar-state~="active"][data-v-a5e0e48e] {
95
+ outline: 2px solid var(--ui-avatar-active-ring, var(--ui-success));
96
+ outline-offset: 1px;
97
+ }
98
+ .image[data-v-a5e0e48e],img[data-v-a5e0e48e-s] {
87
99
  grid-area: 1 / 1;
88
100
  inline-size: 100%;
89
101
  block-size: 100%;
90
102
  object-fit: cover;
91
103
  }
92
- .fallback[data-v-ebb1bbbb] {
104
+ .fallback[data-v-a5e0e48e] {
93
105
  grid-area: 1 / 1;
94
106
  display: inline-flex;
95
107
  align-items: center;
@@ -102,7 +114,7 @@
102
114
  /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
103
115
  * Trimming applies to block containers, so the box is a block with centred content. */
104
116
  @supports (text-box-trim: trim-both) {
105
- .fallback[data-v-ebb1bbbb] {
117
+ .fallback[data-v-a5e0e48e] {
106
118
  display: block;
107
119
  text-align: center;
108
120
  align-content: center;
@@ -110,12 +122,12 @@
110
122
  text-box-edge: cap alphabetic;
111
123
  }
112
124
  }
113
- [hidden][data-v-ebb1bbbb] {
125
+ [hidden][data-v-a5e0e48e] {
114
126
  display: none;
115
127
  }
116
128
 
117
129
  /* A component that sets its display still honours the hidden attribute on its root. */
118
- [data-component~="ui-avatar"][hidden][data-v-ebb1bbbb] {
130
+ [data-component~="ui-avatar"][hidden][data-v-a5e0e48e] {
119
131
  display: none;
120
132
  }
121
133