vueform-plugin-checkbox-select-all 1.0.2 → 1.0.3

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/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{watch as v,onMounted as _,nextTick as g}from"vue";function p(){return{apply:["CheckboxElement","CheckboxgroupElement"],props:{controls:{type:Array,default:null},controller:{type:String,default:null}},setup(c,x,n){let{form$:i,el$:l}=n,o=e=>e?e.type==="checkbox"?e.value===!0:e.type==="checkboxgroup"?e.value?.length>0&&e.value?.length===e.items?.length:!1:!1,h=(e,t)=>{e&&(e.type==="checkbox"?(t&&e.value!==!0&&e.check(),!t&&e.value!==!1&&e.uncheck()):e.type==="checkboxgroup"&&(t&&!o(e)?e.checkAll():!t&&e.value?.length>0&&e.uncheckAll()))};return _(()=>{g(()=>{if(c.controls&&c.controls.length>0&&v(n.value,()=>{if(l.value.__locked){l.value.__locked=!1;return}let e=o(l.value);c.controls.forEach(t=>{let u=i.value.el$(t);u&&h(u,e)})}),c.controller&&v(n.value,()=>{if(l.value.__locked){l.value.__locked=!1;return}let e=i.value.el$(c.controller);if(!e||!e.controls)return;let t=e.controls.every(r=>{let a=i.value.el$(r);return a?o(a):!1}),u=o(e);t!==u&&(e.__locked=!0,h(e,t))}),l.value.type==="checkboxgroup"){let e=l.value.items.find(t=>t.groupController);if(e){let t=e.value,u=l.value.items.filter(r=>r.value!==t).map(r=>r.value);v(n.value,(r,a)=>{if(l.value.__lockedInternal){l.value.__lockedInternal=!1;return}let k=a.includes(t),s=r.includes(t);if(!k&&s){l.value.__lockedInternal=!0,l.value.checkAll();return}if(k&&!s){l.value.__lockedInternal=!0,l.value.uncheckAll();return}let d=u.every(f=>r.includes(f));s&&!d?(l.value.__lockedInternal=!0,l.value.value=r.filter(f=>f!==t)):!s&&d&&(l.value.__lockedInternal=!0,l.value.value=[...r,t])})}}})}),n}}}export{p as default};
package/package.json CHANGED
@@ -1,15 +1,19 @@
1
1
  {
2
2
  "name": "vueform-plugin-checkbox-select-all",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Bi-directional Select All logic for Vueform's Checkbox and Checkboxgroup elements",
5
- "main": "src/index.js",
5
+ "main": "dist/index.js",
6
6
  "type": "module",
7
+ "scripts": {
8
+ "build": "esbuild src/index.js --bundle --minify --format=esm --outfile=dist/index.js --external:vue --external:@vueform/vueform",
9
+ "prepublishOnly": "npm run build"
10
+ },
7
11
  "files": [
8
- "src"
12
+ "dist"
9
13
  ],
10
14
  "peerDependencies": {
11
- "vue": "^3.0.0",
12
- "@vueform/vueform": "^1.0.0"
15
+ "@vueform/vueform": "^1.0.0",
16
+ "vue": "^3.0.0"
13
17
  },
14
18
  "keywords": [
15
19
  "vueform",
@@ -18,5 +22,8 @@
18
22
  "select-all"
19
23
  ],
20
24
  "author": "Mohieb Al-Hesan",
21
- "license": "MIT"
25
+ "license": "MIT",
26
+ "devDependencies": {
27
+ "esbuild": "^0.27.2"
28
+ }
22
29
  }
package/readme.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # Vueform Select All Checkboxes Plugin
2
2
 
3
- This plugin enables complex "Select All" logic for Vueform. It handles bi-directional synchronization (Parent $\leftrightarrow$ Child) and prevents infinite loops using an internal locking mechanism. It supports standard checkboxes, checkbox groups, and nested structures.
3
+ This plugin enables complex "Select All" logic for Vueform. It handles bi-directional synchronization (Parent <--> Child) and prevents infinite loops using an internal locking mechanism. It supports standard checkboxes, checkbox groups, and nested structures.
4
4
 
5
5
  ## 📦 Installation
6
6
 
7
7
  ### 1. Install via NPM
8
+
8
9
  Run the following command in your project root:
9
10
 
10
11
  ```bash
@@ -238,4 +239,4 @@ A group that contains its own "All" option inside the list, and a main checkbox
238
239
  text: "Save My Selections",
239
240
  },
240
241
  }
241
- ```
242
+ ```
package/src/index.js DELETED
@@ -1,144 +0,0 @@
1
- import { watch, onMounted, nextTick } from "vue";
2
-
3
- export default function CheckboxSelectAll() {
4
- return {
5
- apply: ["CheckboxElement", "CheckboxgroupElement"],
6
- props: {
7
- controls: { type: Array, default: null }, // External: Downstream
8
- controller: { type: String, default: null }, // External: Upstream
9
- },
10
- setup(props, context, component) {
11
- const { form$, el$ } = component;
12
-
13
- // --- Helpers ---
14
- const isComplete = (el) => {
15
- if (!el) return false;
16
- if (el.type === "checkbox") return el.value === true;
17
- if (el.type === "checkboxgroup") {
18
- // Complete if selected count equals total options count
19
- return el.value?.length > 0 && el.value?.length === el.items?.length;
20
- }
21
- return false;
22
- };
23
-
24
- const setElementState = (el, makeChecked) => {
25
- if (!el) return;
26
- if (el.type === "checkbox") {
27
- if (makeChecked && el.value !== true) el.check();
28
- if (!makeChecked && el.value !== false) el.uncheck();
29
- } else if (el.type === "checkboxgroup") {
30
- if (makeChecked && !isComplete(el)) el.checkAll();
31
- else if (!makeChecked && el.value?.length > 0) el.uncheckAll();
32
- }
33
- };
34
-
35
- onMounted(() => {
36
- nextTick(() => {
37
- // ---------------------------------------------------------
38
- // 1. EXTERNAL DOWNSTREAM (Main Controller -> This Element)
39
- // ---------------------------------------------------------
40
- if (props.controls && props.controls.length > 0) {
41
- watch(component.value, () => {
42
- if (el$.value.__locked) {
43
- el$.value.__locked = false;
44
- return;
45
- }
46
- const shouldCheck = isComplete(el$.value);
47
- props.controls.forEach((path) => {
48
- const child = form$.value.el$(path);
49
- if (child) setElementState(child, shouldCheck);
50
- });
51
- });
52
- }
53
-
54
- // ---------------------------------------------------------
55
- // 2. EXTERNAL UPSTREAM (This Element -> Main Controller)
56
- // ---------------------------------------------------------
57
- if (props.controller) {
58
- watch(component.value, () => {
59
- if (el$.value.__locked) {
60
- el$.value.__locked = false;
61
- return;
62
- }
63
- const parent = form$.value.el$(props.controller);
64
- if (!parent || !parent.controls) return;
65
-
66
- const allSiblingsChecked = parent.controls.every((path) => {
67
- const sibling = form$.value.el$(path);
68
- return sibling ? isComplete(sibling) : false;
69
- });
70
-
71
- const parentIsChecked = isComplete(parent);
72
- if (allSiblingsChecked !== parentIsChecked) {
73
- parent.__locked = true;
74
- setElementState(parent, allSiblingsChecked);
75
- }
76
- });
77
- }
78
-
79
- // ---------------------------------------------------------
80
- // 3. INTERNAL GROUP LOGIC (CheckboxGroup Only)
81
- // Handles the "All" option inside the items array
82
- // ---------------------------------------------------------
83
- if (el$.value.type === "checkboxgroup") {
84
- // Find the "All" option based on the custom property 'groupController'
85
- const controllerItem = el$.value.items.find(
86
- (option) => option.groupController
87
- );
88
-
89
- if (controllerItem) {
90
- const ctrlVal = controllerItem.value;
91
- const otherVals = el$.value.items
92
- .filter((i) => i.value !== ctrlVal)
93
- .map((i) => i.value);
94
-
95
- watch(component.value, (newVal, oldVal) => {
96
- // If locked by external logic, skip internal calculation
97
- if (el$.value.__lockedInternal) {
98
- el$.value.__lockedInternal = false;
99
- return;
100
- }
101
-
102
- // Determine what happened
103
- const wasChecked = oldVal.includes(ctrlVal);
104
- const isChecked = newVal.includes(ctrlVal);
105
-
106
- // Scenario A: User clicked "All" (Checked it)
107
- if (!wasChecked && isChecked) {
108
- // Lock to prevent infinite recursion
109
- el$.value.__lockedInternal = true;
110
- el$.value.checkAll();
111
- return;
112
- }
113
-
114
- // Scenario B: User clicked "All" (Unchecked it)
115
- if (wasChecked && !isChecked) {
116
- el$.value.__lockedInternal = true;
117
- el$.value.uncheckAll();
118
- return;
119
- }
120
-
121
- // Scenario C: User clicked a Sibling (Check logic)
122
- const othersComplete = otherVals.every((v) =>
123
- newVal.includes(v)
124
- );
125
-
126
- if (isChecked && !othersComplete) {
127
- // "All" is checked, but a sibling is missing -> Uncheck "All"
128
- el$.value.__lockedInternal = true;
129
- el$.value.value = newVal.filter((v) => v !== ctrlVal);
130
- } else if (!isChecked && othersComplete) {
131
- // "All" is unchecked, but all siblings are there -> Check "All"
132
- el$.value.__lockedInternal = true;
133
- el$.value.value = [...newVal, ctrlVal];
134
- }
135
- });
136
- }
137
- }
138
- });
139
- });
140
-
141
- return component;
142
- },
143
- };
144
- }