@threadlabs/looma 0.12.0 → 0.12.1

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.0",
3
+ "version": "0.12.1",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -5,7 +5,9 @@
5
5
  focus ring around the input and its affixes together; the input inside drops its own through
6
6
  its custom properties, so it is still the one ui-input, with its form behaviour intact. The
7
7
  affixes are plain text beside the input, so name the input with a label that says what the
8
- whole value is. */
8
+ whole value is. The action slot takes one button at the end, inside the border, for the one
9
+ thing the field is for ("Continue" after a site's address), so it reads as the field's action
10
+ and not the form's. */
9
11
  :scope {
10
12
  --ui-input-border: transparent;
11
13
  --ui-input-border-hover: transparent;
@@ -35,7 +37,8 @@
35
37
  border-color: var(--ui-text-secondary);
36
38
  }
37
39
 
38
- :scope:focus-within {
40
+ /* The field's focus, not the action's: a focused button draws its own ring. */
41
+ :scope:has(.field :focus) {
39
42
  border-color: var(--ui-accent-solid);
40
43
  box-shadow:
41
44
  var(--ui-control-inset),
@@ -68,7 +71,15 @@
68
71
  white-space: nowrap;
69
72
  }
70
73
 
71
- .affix:empty {
74
+ .action {
75
+ display: flex;
76
+ flex: none;
77
+ align-items: stretch;
78
+ padding: var(--ui-space-1);
79
+ }
80
+
81
+ .affix:empty,
82
+ .action:empty {
72
83
  display: none;
73
84
  }
74
85
 
@@ -83,7 +94,11 @@
83
94
  focus ring around the input and its affixes together; the input inside drops its own through
84
95
  its custom properties, so it is still the one ui-input, with its form behaviour intact. The
85
96
  affixes are plain text beside the input, so name the input with a label that says what the
86
- whole value is. */
97
+ whole value is. The action slot takes one button at the end, inside the border, for the one
98
+ thing the field is for ("Continue" after a site's address), so it reads as the field's action
99
+ and not the form's. */
100
+
101
+ /* The field's focus, not the action's: a focused button draws its own ring. */
87
102
 
88
103
  /* A component that sets its display still honours the hidden attribute on its root. */
89
104
  }
@@ -45,6 +45,17 @@ export function createUiInputGroup(options = {}) {
45
45
  } else {
46
46
  }
47
47
  element.append(element2);
48
+ const element3 = document.createElement("span");
49
+ element3.setAttribute("class", "action");
50
+ if (slots["action"] ?? [].length > 0) {
51
+ for (const child of slots["action"] ?? []) {
52
+ const node = typeof child === "string" ? document.createTextNode(child) : child;
53
+ projected.push([node, "action"]);
54
+ element3.append(node);
55
+ }
56
+ } else {
57
+ }
58
+ element.append(element3);
48
59
  manageGeneratedProps(element, [
49
60
  { name: "disabled", attribute: "data-disabled", value: componentProps["disabled"], default: false, type: "boolean", required: false },
50
61
  ]);
@@ -1,13 +1,15 @@
1
1
  type __VLS_Props = {
2
2
  disabled?: boolean;
3
3
  };
4
- declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {};
4
+ declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {}, __VLS_7: {};
5
5
  type __VLS_Slots = {} & {
6
6
  prefix?: (props: typeof __VLS_1) => any;
7
7
  } & {
8
8
  default?: (props: typeof __VLS_3) => any;
9
9
  } & {
10
10
  suffix?: (props: typeof __VLS_5) => any;
11
+ } & {
12
+ action?: (props: typeof __VLS_7) => any;
11
13
  };
12
14
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
13
15
  disabled: boolean;
@@ -30,6 +30,7 @@ const hostState = computed(() =>
30
30
  <span class="affix"><slot name="prefix" /></span>
31
31
  <span class="field"><slot /></span>
32
32
  <span class="affix"><slot name="suffix" /></span>
33
+ <span class="action"><slot name="action" /></span>
33
34
  </div>
34
35
  </template>
35
36
 
@@ -39,7 +40,9 @@ const hostState = computed(() =>
39
40
  focus ring around the input and its affixes together; the input inside drops its own through
40
41
  its custom properties, so it is still the one ui-input, with its form behaviour intact. The
41
42
  affixes are plain text beside the input, so name the input with a label that says what the
42
- whole value is. */
43
+ whole value is. The action slot takes one button at the end, inside the border, for the one
44
+ thing the field is for ("Continue" after a site's address), so it reads as the field's action
45
+ and not the form's. */
43
46
  [data-component~="ui-input-group"] {
44
47
  --ui-input-border: transparent;
45
48
  --ui-input-border-hover: transparent;
@@ -71,7 +74,8 @@ const hostState = computed(() =>
71
74
  border-color: var(--ui-text-secondary);
72
75
  }
73
76
 
74
- [data-component~="ui-input-group"]:focus-within {
77
+ /* The field's focus, not the action's: a focused button draws its own ring. */
78
+ [data-component~="ui-input-group"]:has(.field :focus) {
75
79
  border-color: var(--ui-accent-solid);
76
80
  box-shadow:
77
81
  var(--ui-control-inset),
@@ -104,7 +108,15 @@ const hostState = computed(() =>
104
108
  white-space: nowrap;
105
109
  }
106
110
 
107
- .affix:empty {
111
+ .action {
112
+ display: flex;
113
+ flex: none;
114
+ align-items: stretch;
115
+ padding: var(--ui-space-1);
116
+ }
117
+
118
+ .affix:empty,
119
+ .action:empty {
108
120
  display: none;
109
121
  }
110
122
 
@@ -5,6 +5,7 @@ var _hoisted_1 = ["data-ui-input-group-state"];
5
5
  var _hoisted_2 = { class: "affix" };
6
6
  var _hoisted_3 = { class: "field" };
7
7
  var _hoisted_4 = { class: "affix" };
8
+ var _hoisted_5 = { class: "action" };
8
9
  //#endregion
9
10
  //#region .build/vue/UiInputGroup.vue
10
11
  var UiInputGroup_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -22,10 +23,11 @@ var UiInputGroup_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @_
22
23
  return openBlock(), createElementBlock("div", mergeProps({ "data-component": "ui-input-group" }, _ctx.$attrs, { "data-ui-input-group-state": hostState.value || void 0 }), [
23
24
  createElementVNode("span", _hoisted_2, [renderSlot(_ctx.$slots, "prefix", {}, void 0, true)]),
24
25
  createElementVNode("span", _hoisted_3, [renderSlot(_ctx.$slots, "default", {}, void 0, true)]),
25
- createElementVNode("span", _hoisted_4, [renderSlot(_ctx.$slots, "suffix", {}, void 0, true)])
26
+ createElementVNode("span", _hoisted_4, [renderSlot(_ctx.$slots, "suffix", {}, void 0, true)]),
27
+ createElementVNode("span", _hoisted_5, [renderSlot(_ctx.$slots, "action", {}, void 0, true)])
26
28
  ], 16, _hoisted_1);
27
29
  };
28
30
  }
29
- }), [["__scopeId", "data-v-42ff173c"]]);
31
+ }), [["__scopeId", "data-v-ac7159ba"]]);
30
32
  //#endregion
31
33
  export { UiInputGroup_default as t };
@@ -3225,8 +3225,10 @@ svg[data-v-c322b7ed-s] {
3225
3225
  focus ring around the input and its affixes together; the input inside drops its own through
3226
3226
  its custom properties, so it is still the one ui-input, with its form behaviour intact. The
3227
3227
  affixes are plain text beside the input, so name the input with a label that says what the
3228
- whole value is. */
3229
- [data-component~="ui-input-group"][data-v-42ff173c] {
3228
+ whole value is. The action slot takes one button at the end, inside the border, for the one
3229
+ thing the field is for ("Continue" after a site's address), so it reads as the field's action
3230
+ and not the form's. */
3231
+ [data-component~="ui-input-group"][data-v-ac7159ba] {
3230
3232
  --ui-input-border: transparent;
3231
3233
  --ui-input-border-hover: transparent;
3232
3234
  --ui-input-focus-border: transparent;
@@ -3252,28 +3254,30 @@ svg[data-v-c322b7ed-s] {
3252
3254
  border-color var(--ui-motion-fast) var(--ui-motion-ease),
3253
3255
  box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
3254
3256
  }
3255
- [data-component~="ui-input-group"][data-v-42ff173c]:hover:not(:focus-within) {
3257
+ [data-component~="ui-input-group"][data-v-ac7159ba]:hover:not(:focus-within) {
3256
3258
  border-color: var(--ui-text-secondary);
3257
3259
  }
3258
- [data-component~="ui-input-group"][data-v-42ff173c]:focus-within {
3260
+
3261
+ /* The field's focus, not the action's: a focused button draws its own ring. */
3262
+ [data-component~="ui-input-group"][data-v-ac7159ba]:has(.field :focus) {
3259
3263
  border-color: var(--ui-accent-solid);
3260
3264
  box-shadow:
3261
3265
  var(--ui-control-inset),
3262
3266
  var(--ui-control-focus-halo-shadow);
3263
3267
  }
3264
- [data-component~="ui-input-group"][data-v-42ff173c]:has([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])) {
3268
+ [data-component~="ui-input-group"][data-v-ac7159ba]:has([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])) {
3265
3269
  border-color: var(--ui-danger-solid);
3266
3270
  }
3267
- [data-component~="ui-input-group"][data-ui-input-group-state~="disabled"][data-v-42ff173c] {
3271
+ [data-component~="ui-input-group"][data-ui-input-group-state~="disabled"][data-v-ac7159ba] {
3268
3272
  background: var(--ui-surface-muted);
3269
3273
  box-shadow: none;
3270
3274
  }
3271
- .field[data-v-42ff173c] {
3275
+ .field[data-v-ac7159ba] {
3272
3276
  display: flex;
3273
3277
  flex: 1;
3274
3278
  min-inline-size: 0;
3275
3279
  }
3276
- .affix[data-v-42ff173c] {
3280
+ .affix[data-v-ac7159ba] {
3277
3281
  display: inline-flex;
3278
3282
  flex: none;
3279
3283
  align-items: center;
@@ -3283,12 +3287,19 @@ svg[data-v-c322b7ed-s] {
3283
3287
  font-size: var(--ui-font-size-sm);
3284
3288
  white-space: nowrap;
3285
3289
  }
3286
- .affix[data-v-42ff173c]:empty {
3290
+ .action[data-v-ac7159ba] {
3291
+ display: flex;
3292
+ flex: none;
3293
+ align-items: stretch;
3294
+ padding: var(--ui-space-1);
3295
+ }
3296
+ .affix[data-v-ac7159ba]:empty,
3297
+ .action[data-v-ac7159ba]:empty {
3287
3298
  display: none;
3288
3299
  }
3289
3300
 
3290
3301
  /* A component that sets its display still honours the hidden attribute on its root. */
3291
- [data-component~="ui-input-group"][hidden][data-v-42ff173c] {
3302
+ [data-component~="ui-input-group"][hidden][data-v-ac7159ba] {
3292
3303
  display: none;
3293
3304
  }
3294
3305