vueform-plugin-checkbox-select-all 1.0.1 → 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.1",
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,12 +1,16 @@
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
- ### 1. Create the Plugin File
7
+ ### 1. Install via NPM
8
8
 
9
- Create a file named `CheckboxSelectAll.js` inside your plugins directory (e.g., `./vueform/plugins/CheckboxSelectAll.js`) and paste the plugin code into it.
9
+ Run the following command in your project root:
10
+
11
+ ```bash
12
+ npm install vueform-plugin-checkbox-select-all
13
+ ```
10
14
 
11
15
  ### 2. Register in `vueform.config.js`
12
16
 
@@ -20,7 +24,7 @@ import { defineConfig } from "@vueform/vueform";
20
24
  import "@vueform/vueform/dist/vueform.css";
21
25
 
22
26
  // 1. Import the custom plugin
23
- import CheckboxSelectAll from "./vueform/plugins/CheckboxSelectAll";
27
+ import CheckboxSelectAll from "vueform-plugin-checkbox-select-all";
24
28
 
25
29
  export default defineConfig({
26
30
  theme: vueform,
@@ -235,4 +239,4 @@ A group that contains its own "All" option inside the list, and a main checkbox
235
239
  text: "Save My Selections",
236
240
  },
237
241
  }
238
- ```
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
- }