@charpente-ui/vue 2.1.1 → 2.2.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 (33) hide show
  1. package/README.md +14 -0
  2. package/dist/components/BaseButton.js +1 -1
  3. package/dist/components/BaseCheckbox.js +2 -2
  4. package/dist/components/BaseCheckboxGroup.js +1 -1
  5. package/dist/components/BaseField.js +28 -12
  6. package/dist/components/BaseFile.js +1 -1
  7. package/dist/components/BaseForm.js +1 -1
  8. package/dist/components/BaseInput.js +1 -1
  9. package/dist/components/BaseLabel.js +1 -1
  10. package/dist/components/BaseRadio.js +2 -2
  11. package/dist/components/BaseRadioGroup.js +1 -1
  12. package/dist/components/BaseSelect.js +1 -1
  13. package/dist/components/BaseSupportingText.js +7 -7
  14. package/dist/components/BaseTextarea.js +1 -1
  15. package/dist/index.d.ts +1 -13
  16. package/dist/{components → src/components}/BaseField.d.ts +4 -1
  17. package/dist/{components → src/components}/internal/keys.d.ts +3 -1
  18. package/dist/src/index.d.ts +13 -0
  19. package/package.json +19 -16
  20. /package/dist/{components → src/components}/BaseButton.d.ts +0 -0
  21. /package/dist/{components → src/components}/BaseCheckbox.d.ts +0 -0
  22. /package/dist/{components → src/components}/BaseCheckboxGroup.d.ts +0 -0
  23. /package/dist/{components → src/components}/BaseFile.d.ts +0 -0
  24. /package/dist/{components → src/components}/BaseForm.d.ts +0 -0
  25. /package/dist/{components → src/components}/BaseInput.d.ts +0 -0
  26. /package/dist/{components → src/components}/BaseLabel.d.ts +0 -0
  27. /package/dist/{components → src/components}/BaseRadio.d.ts +0 -0
  28. /package/dist/{components → src/components}/BaseRadioGroup.d.ts +0 -0
  29. /package/dist/{components → src/components}/BaseSelect.d.ts +0 -0
  30. /package/dist/{components → src/components}/BaseSupportingText.d.ts +0 -0
  31. /package/dist/{components → src/components}/BaseTextarea.d.ts +0 -0
  32. /package/dist/{components → src/components}/internal/field.d.ts +0 -0
  33. /package/dist/{components → src/components}/internal/modifiers.d.ts +0 -0
package/README.md CHANGED
@@ -248,6 +248,20 @@ messages for free. Charpente UI exposes that instead of reinventing it — opt i
248
248
  - Without `validate`, nothing changes — bring your own validation library if you need cross-field or async rules.
249
249
  Native escapes still work: `formnovalidate` on a submit button skips validation for that button.
250
250
 
251
+ `CField` stays zero-CSS: it never applies a class itself. If you need custom styling beyond `[aria-invalid]` or
252
+ `:invalid` selectors, its default slot exposes `invalid` and `message` so you can drive your own classes:
253
+
254
+ ```vue
255
+ <CField v-slot="{ invalid, message }">
256
+ <CLabel>Email</CLabel>
257
+ <CInput v-model="email" type="email" required :class="{ 'is-invalid': invalid }"/>
258
+ <span v-if="invalid" class="error">{{ message }}</span>
259
+ </CField>
260
+ ```
261
+
262
+ This only reaches elements placed directly inside `CField`'s default slot — a custom component nested deeper won't
263
+ receive `invalid`/`message` automatically; pass them down as props if you need that.
264
+
251
265
  ## Components
252
266
 
253
267
  | Name | Core Logic | Tag | Status |
@@ -1,6 +1,6 @@
1
1
  import { computed as e, createBlock as t, defineComponent as n, mergeProps as r, openBlock as i, renderSlot as a, resolveDynamicComponent as o, useAttrs as s, withCtx as c } from "vue";
2
2
  //#region src/components/BaseButton.vue?vue&type=script&setup=true&lang.ts
3
- var l = /* @__PURE__ */ n({
3
+ var l = /*@__PURE__*/ n({
4
4
  inheritAttrs: !1,
5
5
  __name: "BaseButton",
6
6
  props: { as: { default: "button" } },
@@ -8,10 +8,10 @@ var _ = [
8
8
  "aria-invalid",
9
9
  "name",
10
10
  "value"
11
- ], v = /* @__PURE__ */ i({
11
+ ], v = /*@__PURE__*/ i({
12
12
  inheritAttrs: !1,
13
13
  __name: "BaseCheckbox",
14
- props: /* @__PURE__ */ s({
14
+ props: /*@__PURE__*/ s({
15
15
  value: {},
16
16
  indeterminate: { type: Boolean }
17
17
  }, {
@@ -1,7 +1,7 @@
1
1
  import { checkboxGroupKey as e, fieldKey as t } from "./internal/keys.js";
2
2
  import { computed as n, createElementBlock as r, defineComponent as i, guardReactiveProps as a, normalizeProps as o, openBlock as s, provide as c, renderSlot as l, useAttrs as u, useId as d, useModel as f } from "vue";
3
3
  //#region src/components/BaseCheckboxGroup.vue?vue&type=script&setup=true&lang.ts
4
- var p = /* @__PURE__ */ i({
4
+ var p = /*@__PURE__*/ i({
5
5
  inheritAttrs: !1,
6
6
  __name: "BaseCheckboxGroup",
7
7
  props: {
@@ -1,30 +1,46 @@
1
1
  import { fieldKey as e } from "./internal/keys.js";
2
2
  import { computed as t, createElementBlock as n, defineComponent as r, mergeProps as i, openBlock as a, provide as o, ref as s, renderSlot as c, useAttrs as l, useId as u } from "vue";
3
3
  //#region src/components/BaseField.vue?vue&type=script&setup=true&lang.ts
4
- var d = /* @__PURE__ */ r({
4
+ var d = /*@__PURE__*/ r({
5
5
  inheritAttrs: !1,
6
6
  __name: "BaseField",
7
7
  setup(r) {
8
- let d = l(), f = u(), p = s(), m = s(""), h = s(!1), g = t(() => typeof d.id == "string" ? d.id : f), _ = t(() => {
8
+ let d = l(), f = u(), p = s([]), m = s(""), h = s(!1), g = t(() => typeof d.id == "string" ? d.id : f), _ = t(() => p.value.at(-1));
9
+ function v(e) {
10
+ p.value.push(e);
11
+ }
12
+ function y(e) {
13
+ let t = p.value.indexOf(e);
14
+ t !== -1 && p.value.splice(t, 1);
15
+ }
16
+ let b = t(() => {
9
17
  let e = { ...d };
10
18
  return delete e.id, e;
11
19
  });
12
20
  o(e, {
13
21
  id: g,
14
- supportingTextId: p,
15
- validationMessage: m
22
+ supportingTextId: _,
23
+ validationMessage: m,
24
+ registerSupportingText: v,
25
+ unregisterSupportingText: y
16
26
  });
17
- function v(e) {
27
+ function x(e) {
18
28
  h.value = !0, m.value = e.target.validationMessage;
19
29
  }
20
- function y(e) {
21
- h.value && (m.value = e.target.validationMessage);
30
+ function S(e) {
31
+ if (h.value) {
32
+ let t = e.target;
33
+ h.value = !t.validity.valid, m.value = t.validationMessage;
34
+ }
22
35
  }
23
- return (e, t) => (a(), n("div", i(_.value, {
24
- onInvalidCapture: v,
25
- onInputCapture: y,
26
- onChangeCapture: y
27
- }), [c(e.$slots, "default")], 16));
36
+ return (e, t) => (a(), n("div", i(b.value, {
37
+ onInvalidCapture: x,
38
+ onInputCapture: S,
39
+ onChangeCapture: S
40
+ }), [c(e.$slots, "default", {
41
+ invalid: h.value,
42
+ message: m.value
43
+ })], 16));
28
44
  }
29
45
  });
30
46
  //#endregion
@@ -5,7 +5,7 @@ var l = [
5
5
  "id",
6
6
  "aria-describedby",
7
7
  "aria-invalid"
8
- ], u = /* @__PURE__ */ n({
8
+ ], u = /*@__PURE__*/ n({
9
9
  inheritAttrs: !1,
10
10
  __name: "BaseFile",
11
11
  props: {
@@ -1,6 +1,6 @@
1
1
  import { computed as e, createElementBlock as t, defineComponent as n, mergeProps as r, openBlock as i, renderSlot as a, useAttrs as o, useId as s, withModifiers as c } from "vue";
2
2
  //#region src/components/BaseForm.vue?vue&type=script&setup=true&lang.ts
3
- var l = ["id", "novalidate"], u = /* @__PURE__ */ n({
3
+ var l = ["id", "novalidate"], u = /*@__PURE__*/ n({
4
4
  inheritAttrs: !1,
5
5
  __name: "BaseForm",
6
6
  props: { validate: { type: Boolean } },
@@ -10,7 +10,7 @@ var d = [
10
10
  "id",
11
11
  "aria-describedby",
12
12
  "aria-invalid"
13
- ], p = /* @__PURE__ */ r({
13
+ ], p = /*@__PURE__*/ r({
14
14
  inheritAttrs: !1,
15
15
  __name: "BaseInput",
16
16
  props: {
@@ -1,7 +1,7 @@
1
1
  import { fieldKey as e } from "./internal/keys.js";
2
2
  import { computed as t, createElementBlock as n, defineComponent as r, inject as i, mergeProps as a, openBlock as o, renderSlot as s } from "vue";
3
3
  //#region src/components/BaseLabel.vue?vue&type=script&setup=true&lang.ts
4
- var c = ["for"], l = /* @__PURE__ */ r({
4
+ var c = ["for"], l = /*@__PURE__*/ r({
5
5
  inheritAttrs: !1,
6
6
  __name: "BaseLabel",
7
7
  props: { for: {} },
@@ -8,10 +8,10 @@ var h = [
8
8
  "aria-invalid",
9
9
  "name",
10
10
  "value"
11
- ], g = /* @__PURE__ */ i({
11
+ ], g = /*@__PURE__*/ i({
12
12
  inheritAttrs: !1,
13
13
  __name: "BaseRadio",
14
- props: /* @__PURE__ */ s({ value: {} }, {
14
+ props: /*@__PURE__*/ s({ value: {} }, {
15
15
  modelValue: {},
16
16
  modelModifiers: {}
17
17
  }),
@@ -1,7 +1,7 @@
1
1
  import { fieldKey as e, radioGroupKey as t } from "./internal/keys.js";
2
2
  import { computed as n, createElementBlock as r, defineComponent as i, guardReactiveProps as a, normalizeProps as o, openBlock as s, provide as c, renderSlot as l, useAttrs as u, useId as d, useModel as f } from "vue";
3
3
  //#region src/components/BaseRadioGroup.vue?vue&type=script&setup=true&lang.ts
4
- var p = /* @__PURE__ */ i({
4
+ var p = /*@__PURE__*/ i({
5
5
  inheritAttrs: !1,
6
6
  __name: "BaseRadioGroup",
7
7
  props: {
@@ -5,7 +5,7 @@ var u = [
5
5
  "id",
6
6
  "aria-describedby",
7
7
  "aria-invalid"
8
- ], d = /* @__PURE__ */ n({
8
+ ], d = /*@__PURE__*/ n({
9
9
  inheritAttrs: !1,
10
10
  __name: "BaseSelect",
11
11
  props: {
@@ -1,17 +1,17 @@
1
1
  import { fieldKey as e } from "./internal/keys.js";
2
- import { Fragment as t, computed as n, createElementBlock as r, createTextVNode as i, defineComponent as a, inject as o, mergeProps as s, onBeforeUnmount as c, openBlock as l, renderSlot as u, toDisplayString as d, useAttrs as f, useId as p, watchEffect as m } from "vue";
2
+ import { Fragment as t, computed as n, createElementBlock as r, createTextVNode as i, defineComponent as a, inject as o, mergeProps as s, onBeforeUnmount as c, openBlock as l, renderSlot as u, toDisplayString as d, useAttrs as f, useId as p, watch as m } from "vue";
3
3
  //#region src/components/BaseSupportingText.vue?vue&type=script&setup=true&lang.ts
4
- var h = ["id"], g = /* @__PURE__ */ a({
4
+ var h = ["id"], g = /*@__PURE__*/ a({
5
5
  inheritAttrs: !1,
6
6
  __name: "BaseSupportingText",
7
7
  props: { validation: { type: Boolean } },
8
8
  setup(a) {
9
9
  let g = a, _ = f(), v = p(), y = o(e, null), b = n(() => typeof _.id == "string" ? _.id : v), x = n(() => g.validation ? y?.validationMessage.value ?? "" : "");
10
- return m(() => {
11
- y && (y.supportingTextId.value = b.value);
12
- }), c(() => {
13
- y && (y.supportingTextId.value = void 0);
14
- }), (e, n) => (l(), r("p", s(e.$attrs, { id: b.value }), [x.value ? (l(), r(t, { key: 0 }, [i(d(x.value), 1)], 64)) : u(e.$slots, "default", { key: 1 })], 16, h));
10
+ return m(b, (e, t) => {
11
+ y && (t && y.unregisterSupportingText(t), y.registerSupportingText(e));
12
+ }, { immediate: !0 }), c(() => {
13
+ y?.unregisterSupportingText(b.value);
14
+ }), (e, n) => (l(), r("p", s(e.$attrs, { id: b.value }), [x.value ? (l(), r(t, { key: 0 }, [i(d(x.value), 1)], 64)) : u(e.$slots, "default", {}, void 0, void 0, 1)], 16, h));
15
15
  }
16
16
  });
17
17
  //#endregion
@@ -10,7 +10,7 @@ var d = [
10
10
  "id",
11
11
  "aria-describedby",
12
12
  "aria-invalid"
13
- ], p = /* @__PURE__ */ r({
13
+ ], p = /*@__PURE__*/ r({
14
14
  inheritAttrs: !1,
15
15
  __name: "BaseTextarea",
16
16
  props: {
package/dist/index.d.ts CHANGED
@@ -1,13 +1 @@
1
- export { default as CButton } from './components/BaseButton';
2
- export { default as CCheckbox } from './components/BaseCheckbox';
3
- export { default as CCheckboxGroup } from './components/BaseCheckboxGroup';
4
- export { default as CField } from './components/BaseField';
5
- export { default as CFile } from './components/BaseFile';
6
- export { default as CForm } from './components/BaseForm';
7
- export { default as CInput } from './components/BaseInput';
8
- export { default as CLabel } from './components/BaseLabel';
9
- export { default as CRadio } from './components/BaseRadio';
10
- export { default as CRadioGroup } from './components/BaseRadioGroup';
11
- export { default as CSelect } from './components/BaseSelect';
12
- export { default as CSupportingText } from './components/BaseSupportingText';
13
- export { default as CTextarea } from './components/BaseTextarea';
1
+ export {}
@@ -1,7 +1,10 @@
1
1
  declare function __VLS_template(): {
2
2
  attrs: Partial<{}>;
3
3
  slots: {
4
- default?(_: {}): any;
4
+ default?(_: {
5
+ invalid: boolean;
6
+ message: string;
7
+ }): any;
5
8
  };
6
9
  refs: {};
7
10
  rootEl: any;
@@ -11,7 +11,9 @@ export interface CheckboxGroupContext {
11
11
  export declare const checkboxGroupKey: InjectionKey<CheckboxGroupContext>;
12
12
  export interface FieldContext {
13
13
  id: ComputedRef<string>;
14
- supportingTextId: Ref<string | undefined>;
14
+ supportingTextId: ComputedRef<string | undefined>;
15
15
  validationMessage: Ref<string>;
16
+ registerSupportingText: (id: string) => void;
17
+ unregisterSupportingText: (id: string) => void;
16
18
  }
17
19
  export declare const fieldKey: InjectionKey<FieldContext | null>;
@@ -0,0 +1,13 @@
1
+ export { default as CButton } from './components/BaseButton';
2
+ export { default as CCheckbox } from './components/BaseCheckbox';
3
+ export { default as CCheckboxGroup } from './components/BaseCheckboxGroup';
4
+ export { default as CField } from './components/BaseField';
5
+ export { default as CFile } from './components/BaseFile';
6
+ export { default as CForm } from './components/BaseForm';
7
+ export { default as CInput } from './components/BaseInput';
8
+ export { default as CLabel } from './components/BaseLabel';
9
+ export { default as CRadio } from './components/BaseRadio';
10
+ export { default as CRadioGroup } from './components/BaseRadioGroup';
11
+ export { default as CSelect } from './components/BaseSelect';
12
+ export { default as CSupportingText } from './components/BaseSupportingText';
13
+ export { default as CTextarea } from './components/BaseTextarea';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@charpente-ui/vue",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "description": "Charpente UI is a headless Vue component library.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -10,6 +10,8 @@
10
10
  "build": "vite build",
11
11
  "test": "vitest",
12
12
  "test:coverage": "vitest run --coverage",
13
+ "test:e2e": "playwright test",
14
+ "test:all": "run-s test:coverage test:e2e",
13
15
  "prepare": "husky",
14
16
  "prepack": "npm run build",
15
17
  "release": "semantic-release"
@@ -29,27 +31,28 @@
29
31
  "./package.json": "./package.json"
30
32
  },
31
33
  "devDependencies": {
32
- "@commitlint/cli": "^20.4.2",
33
- "@commitlint/config-conventional": "^20.4.2",
34
+ "@commitlint/cli": "^20.5.3",
35
+ "@commitlint/config-conventional": "^20.5.3",
34
36
  "@front-factory/eslint-config": "^1.3.1",
37
+ "@playwright/test": "^1.61.1",
35
38
  "@semantic-release/changelog": "^6.0.3",
36
39
  "@semantic-release/git": "^10.0.1",
37
- "@semantic-release/github": "^12.0.6",
38
- "@vitejs/plugin-vue": "^6.0.4",
39
- "@vitest/coverage-v8": "^4.1.5",
40
- "@vue/test-utils": "^2.4.9",
41
- "conventional-changelog-conventionalcommits": "^9.1.0",
42
- "eslint": "^10.0.2",
43
- "eslint-plugin-vue": "^10.8.0",
40
+ "@semantic-release/github": "^12.0.9",
41
+ "@vitejs/plugin-vue": "^6.0.8",
42
+ "@vitest/coverage-v8": "^4.1.10",
43
+ "@vue/test-utils": "^2.4.11",
44
+ "conventional-changelog-conventionalcommits": "^9.3.1",
45
+ "eslint": "^10.7.0",
46
+ "eslint-plugin-vue": "^10.10.0",
44
47
  "husky": "^9.1.7",
45
- "jsdom": "^29.1.0",
48
+ "jsdom": "^29.1.1",
46
49
  "npm-run-all2": "^8.0.4",
47
- "semantic-release": "^25.0.3",
48
- "typescript-eslint": "^8.56.1",
49
- "vite": "^8.0.10",
50
+ "semantic-release": "^25.0.8",
51
+ "typescript-eslint": "^8.65.0",
52
+ "vite": "^8.1.5",
50
53
  "vite-plugin-dts": "^4.5.4",
51
- "vitest": "^4.1.5",
52
- "vue": "^3.5.29"
54
+ "vitest": "^4.1.10",
55
+ "vue": "^3.5.40"
53
56
  },
54
57
  "peerDependencies": {
55
58
  "vue": "^3.5.0"