@fiscozen/checkbox 0.1.0 → 0.1.2

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": "@fiscozen/checkbox",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Design System Checkbox and Checkbox Group component",
5
5
  "main": "src/index.ts",
6
6
  "type": "module",
@@ -13,7 +13,7 @@
13
13
  "peerDependencies": {
14
14
  "tailwindcss": "^3.4.1",
15
15
  "vue": "^3.4.13",
16
- "@fiscozen/icons": "^0.1.3"
16
+ "@fiscozen/icons": "^0.1.4"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@rushstack/eslint-patch": "^1.3.3",
@@ -34,10 +34,10 @@
34
34
  "@awesome.me/kit-8137893ad3": "^1.0.65",
35
35
  "@fortawesome/fontawesome-svg-core": "^6.5.1",
36
36
  "@fortawesome/vue-fontawesome": "^3.0.6",
37
- "@fiscozen/eslint-config": "^0.1.0",
38
- "@fiscozen/prettier-config": "^0.1.0",
39
37
  "@fiscozen/tsconfig": "^0.1.0",
40
- "@fiscozen/icons": "^0.1.3"
38
+ "@fiscozen/eslint-config": "^0.1.0",
39
+ "@fiscozen/icons": "^0.1.4",
40
+ "@fiscozen/prettier-config": "^0.1.0"
41
41
  },
42
42
  "license": "MIT",
43
43
  "scripts": {
@@ -2,7 +2,7 @@
2
2
  <div class="flex justify-center flex-col w-fit">
3
3
  <input
4
4
  type="checkbox"
5
- :id="value.replace(/ /g, '-').toLowerCase()"
5
+ :id="id"
6
6
  :disabled="disabled"
7
7
  :checked="checked"
8
8
  :class="staticInputClass"
@@ -13,10 +13,7 @@
13
13
  :indeterminate="indeterminate"
14
14
  ref="refCheckbox"
15
15
  />
16
- <label
17
- :for="value.replace(/ /g, '-').toLowerCase()"
18
- :class="[staticLabelClass, computedLabelClass]"
19
- >
16
+ <label :for="id" :class="[staticLabelClass, computedLabelClass]">
20
17
  <FzIcon
21
18
  :name="computedName"
22
19
  :size="size"
@@ -44,9 +41,13 @@ const props = withDefaults(defineProps<FzCheckboxProps>(), {
44
41
  indeterminate: false,
45
42
  });
46
43
 
47
- const value = props.value || props.label;
44
+ const currentValue = computed(() => props.value ?? props.label);
48
45
 
49
- const model = defineModel<boolean | string[]>({
46
+ const id = computed(
47
+ () => `fz-checkbox-${Math.random().toString(36).slice(2, 9)}`,
48
+ );
49
+
50
+ const model = defineModel<boolean | (string | number | boolean)[]>({
50
51
  required: true,
51
52
  });
52
53
 
@@ -96,7 +97,7 @@ const checkValueIsInModel = () => {
96
97
  if (typeof model.value === "boolean") {
97
98
  return model.value;
98
99
  } else {
99
- return model.value.includes(value);
100
+ return model.value.includes(currentValue.value);
100
101
  }
101
102
  };
102
103
 
@@ -130,9 +131,9 @@ onMounted(() => {
130
131
  if (model.value) refCheckbox.value?.dispatchEvent(new Event("change"));
131
132
  else if (props.checked !== undefined) model.value = props.checked;
132
133
  } else {
133
- if (model.value.includes(value))
134
+ if (model.value.includes(currentValue.value))
134
135
  refCheckbox.value?.dispatchEvent(new Event("change"));
135
- else if (props.checked) model.value.push(value);
136
+ else if (props.checked) model.value.push(currentValue.value);
136
137
  }
137
138
  });
138
139
  </script>
@@ -9,10 +9,10 @@
9
9
  <div :class="[staticSlotContainerClass, computedSlotContainerClass]">
10
10
  <FzCheckboxGroupOption
11
11
  v-for="option in options"
12
- :key="option.value"
12
+ :key="option.value ? option.value.toString() : option.label"
13
13
  v-model="model"
14
- v-bind="option"
15
14
  :disabled="disabled"
15
+ v-bind="option"
16
16
  :emphasis="emphasis"
17
17
  :error="error"
18
18
  :size="size"
@@ -26,11 +26,15 @@
26
26
 
27
27
  <script setup lang="ts">
28
28
  import { computed } from "vue";
29
- import { FzCheckboxGroupProps, ParentCheckbox } from "./types";
29
+ import { FzCheckboxGroupProps } from "./types";
30
30
  import FzCheckboxErrorText from "./components/FzCheckboxErrorText.vue";
31
31
  import { mapSizeToClasses } from "./common";
32
32
  import FzCheckboxGroupOption from "./components/FzCheckboxGroupOption.vue";
33
33
 
34
+ FzCheckboxGroupOption.compatConfig = {
35
+ MODE: 3,
36
+ };
37
+
34
38
  const props = defineProps<FzCheckboxGroupProps>();
35
39
  const id = `fz-checkbox-group-${generateRandomId()}`;
36
40
 
@@ -3,6 +3,8 @@ import { mount } from "@vue/test-utils";
3
3
  import { describe, it, expect } from "vitest";
4
4
  import FzCheckbox from "../FzCheckbox.vue";
5
5
 
6
+ const MAX_CHECKBOX = 200;
7
+
6
8
  describe("FzCheckbox", () => {
7
9
  it("renders correctly", async () => {
8
10
  const wrapper = mount(FzCheckbox, {
@@ -16,7 +18,6 @@ describe("FzCheckbox", () => {
16
18
 
17
19
  await wrapper.vm.$nextTick();
18
20
  expect(wrapper.html()).toContain("Test Checkbox");
19
- expect(wrapper.html()).toMatchSnapshot();
20
21
  });
21
22
 
22
23
  it("emits an update event when clicked", async () => {
@@ -85,4 +86,23 @@ describe("FzCheckbox", () => {
85
86
  await wrapper.vm.$nextTick();
86
87
  expect(wrapper.find("input").element.disabled).toBe(true);
87
88
  });
89
+
90
+ it(`should render ${MAX_CHECKBOX} checkbox all with different ids`, async () => {
91
+ const checkboxes = Array.from({ length: MAX_CHECKBOX }).map((_) => {
92
+ return mount(FzCheckbox, {
93
+ props: {
94
+ label: "Test Checkbox",
95
+ value: "test",
96
+ size: "md",
97
+ modelValue: false,
98
+ disabled: true,
99
+ },
100
+ });
101
+ });
102
+ await Promise.all(checkboxes.map((c) => c.vm.$nextTick()));
103
+ const ids = checkboxes.map((c) => c.find("input").attributes("id"));
104
+ const labelFor = checkboxes.map((c) => c.find("label").attributes("for"));
105
+ expect(new Set(ids).size).toBe(MAX_CHECKBOX);
106
+ expect(new Set(labelFor).size).toBe(MAX_CHECKBOX);
107
+ });
88
108
  });
@@ -14,10 +14,10 @@
14
14
  <div :class="[staticChildContainerClass, computedChildContainerClasses]">
15
15
  <FzCheckbox
16
16
  v-for="child in children"
17
- :key="child.value"
17
+ :key="child.value ? child.value.toString() : child.label"
18
18
  v-model="model"
19
- v-bind="child"
20
19
  :disabled="disabled"
20
+ v-bind="child"
21
21
  :emphasis="emphasis"
22
22
  :error="error"
23
23
  :size="size"
@@ -32,9 +32,13 @@ import { computed } from "vue";
32
32
  import FzCheckbox from "../FzCheckbox.vue";
33
33
  import { ParentCheckbox } from "../types";
34
34
 
35
- const props = defineProps<ParentCheckbox & { size: "sm" | "md" }>();
35
+ FzCheckbox.compatConfig = {
36
+ MODE: 3,
37
+ };
36
38
 
37
- const model = defineModel<string[]>({
39
+ const props = defineProps<ParentCheckbox & { size: "sm" | "md" }>();
40
+ const currentValue = computed(() => props.value ?? props.label);
41
+ const model = defineModel<(string | number | boolean)[]>({
38
42
  required: true,
39
43
  default: [],
40
44
  });
@@ -50,7 +54,7 @@ const isIndeterminate = computed(() => {
50
54
  if (!props.children) return false;
51
55
 
52
56
  const numChecked = props.children.filter((child) =>
53
- model.value.includes(child.value || child.label),
57
+ model.value.includes(child.value ?? child.label),
54
58
  ).length;
55
59
  return numChecked > 0 && numChecked < props.children.length;
56
60
  });
@@ -58,28 +62,26 @@ const isIndeterminate = computed(() => {
58
62
  function handleCheckboxParentChange() {
59
63
  if (!props.children) return;
60
64
  const numChecked = props.children.filter((child) =>
61
- model.value.includes(child.value || child.label),
65
+ model.value.includes(child.value ?? child.label),
62
66
  ).length;
63
67
 
64
68
  if (numChecked === props.children.length) {
65
69
  // push parent value to model (using concat to force reactivity, push seems to not work)
66
- model.value = model.value.concat(props.value || props.label);
70
+ model.value = model.value.concat(currentValue.value);
67
71
  } else {
68
72
  // remove parent value from model if it exists
69
- if (model.value.includes(props.value || props.label))
70
- model.value = model.value.filter(
71
- (value) => value !== (props.value || props.label),
72
- );
73
+ if (model.value.includes(currentValue.value))
74
+ model.value = model.value.filter((value) => value !== currentValue.value);
73
75
  }
74
76
  }
75
77
 
76
78
  function onCheckboxParentChange() {
77
79
  if (!props.children) return;
78
- if (model.value.includes(props.value || props.label)) {
80
+ if (model.value.includes(currentValue.value)) {
79
81
  // push all children values to model that are not already in model
80
82
  model.value = model.value.concat(
81
83
  props.children
82
- ?.map((child) => child.value || child.label)
84
+ ?.map((child) => child.value ?? child.label)
83
85
  .filter((value) => !model.value.includes(value)),
84
86
  );
85
87
  } else {
@@ -87,7 +89,7 @@ function onCheckboxParentChange() {
87
89
  model.value = model.value.filter(
88
90
  (value) =>
89
91
  !props.children
90
- ?.map((child) => child.value || child.label)
92
+ ?.map((child) => child.value ?? child.label)
91
93
  .includes(value),
92
94
  );
93
95
  }
package/src/types.ts CHANGED
@@ -6,7 +6,7 @@ export type FzCheckboxProps = {
6
6
  /**
7
7
  * The value of the checkbox. If not provided, the value will be the label
8
8
  */
9
- value?: string;
9
+ value?: string | number | boolean;
10
10
  /**
11
11
  * The size of the checkbox
12
12
  */
@@ -1,21 +0,0 @@
1
- // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
-
3
- exports[`FzCheckbox > renders correctly 1`] = `
4
- "<div class="flex justify-center flex-col w-fit"><input type="checkbox" id="test" class="w-0 h-0 peer" value="test"><label for="test" class="flex items-start gap-4 hover:cursor-pointer
5
- peer-focus:[&amp;_div]:after:border-1
6
- peer-focus:[&amp;_div]:after:border-solid
7
- peer-focus:[&amp;_div]:after:rounded-[3px]
8
- peer-focus:[&amp;_div]:after:border-blue-500
9
- peer-focus:[&amp;_div]:after:content-['']
10
- peer-focus:[&amp;_div]:after:top-0
11
- peer-focus:[&amp;_div]:after:left-0
12
- peer-focus:[&amp;_div]:after:right-0
13
- peer-focus:[&amp;_div]:after:bottom-0
14
- peer-focus:[&amp;_div]:after:absolute text-md text-grey-500">
15
- <div class="flex items-center justify-center w-[20px] h-[20px] relative mt-2 text-grey-500"><svg class="svg-inline--fa fa-square h-[16px]" aria-hidden="true" focusable="false" data-prefix="far" data-icon="square" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
16
- <path class="" fill="currentColor" d="M384 80c8.8 0 16 7.2 16 16V416c0 8.8-7.2 16-16 16H64c-8.8 0-16-7.2-16-16V96c0-8.8 7.2-16 16-16H384zM64 32C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H64z"></path>
17
- </svg></div><span class="w-fit">Test Checkbox</span>
18
- </label>
19
- <!--v-if-->
20
- </div>"
21
- `;