@jswork/react-render-controls 1.2.2 → 1.2.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/main.cjs.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var c=Object.defineProperty,A=Object.defineProperties;var M=Object.getOwnPropertyDescriptors;var d=Object.getOwnPropertySymbols;var V=Object.prototype.hasOwnProperty,b=Object.prototype.propertyIsEnumerable;var s=(t,e,n)=>e in t?c(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,p=(t,e)=>{for(var n in e||(e={}))V.call(e,n)&&s(t,n,e[n]);if(d)for(var n of d(e))b.call(e,n)&&s(t,n,e[n]);return t},m=(t,e)=>A(t,M(e)),o=(t,e)=>c(t,"name",{value:e,configurable:!0});var _react = require('react'); var _react2 = _interopRequireDefault(_react);var h,l=typeof process!="undefined"&&((h=process.env)==null?void 0:h.NODE_ENV)!=="production";function g(t){return typeof t=="function"}o(g,"isRenderFn");function x(t,e,n,r){if(r===void 0)return e;if(typeof r=="function")return r(t,e,n);let i=t[r];return i==null?(l&&console.warn(`RenderList: keyBy="${String(r)}" but the field is undefined in ${JSON.stringify(t)}`),e):i}o(x,"getKey");function R({items:t,render:e,keyBy:n}){return _react2.default.createElement(_react2.default.Fragment,null,t.map((r,i)=>{let f=x(r,i,t,n);if(g(e))return _react2.default.createElement(_react2.default.Fragment,{key:f},e(r,i,t));let{component:a,dataKey:w="item",props:C={}}=e,I=m(p({},C),{[w]:r});return _react2.default.createElement(_react2.default.Fragment,{key:f},_react2.default.createElement(a,I))}))}o(R,"RenderList");function F({when:t,children:e}){let n=_react.Children.toArray(e);return n.length===0?null:(n.length>2&&l&&console.warn(`RenderIf: Expected at most 2 children, but got ${n.length}. Only the first 2 children will be used.`),n.length===1?t?n[0]:null:t?n[0]:n[1])}o(F,"RenderIf");var S=F;function y(t,e){for(let n=0;n<e.length;n++){let r=e[n];if(typeof r=="string"){if(r===t)return n}else if(r.includes(t))return n}return-1}o(y,"findMatchIndex");function v(t){let e=[];for(let n of t)typeof n=="string"?e.push(n):e.push(...n);return e}o(v,"getAllValues");function L({value:t,items:e,children:n}){var f;let r=y(t,e);if(r===-1){if(l){let a=v(e);console.warn(`RenderMatch: Value "${t}" not found in any of the items. Available values: [${a.join(", ")}]`)}return null}let i=_react.Children.toArray(n).filter(a=>_react.isValidElement.call(void 0, a));return r>=i.length?(l&&console.warn(`RenderMatch: Not enough children provided. Expected at least ${r+1}, but got ${i.length}.`),null):(f=i[r])!=null?f:null}o(L,"RenderMatch");var O=L;function E(t){for(let e=0;e<t.length;e++)if(t[e])return e;return-1}o(E,"findTrueCaseIndex");function $(t,e,n){l&&t>e&&console.warn(`${n}: More cases (${t}) than children (${e}). Extra cases will be ignored.`)}o($,"validateCasesLength");function J({cases:t,children:e,fallback:n=null}){let r=_react.Children.toArray(e).filter(f=>_react.isValidElement.call(void 0, f));$(t.length,r.length,"RenderSwitch");let i=E(t);return i>=0&&i<r.length?r[i]:n}o(J,"RenderSwitch");var P=J;exports.RenderIf = S; exports.RenderList = R; exports.RenderMatch = O; exports.RenderSwitch = P;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var p=Object.defineProperty,V=Object.defineProperties;var b=Object.getOwnPropertyDescriptors;var c=Object.getOwnPropertySymbols;var D=Object.prototype.hasOwnProperty,F=Object.prototype.propertyIsEnumerable;var s=(t,e,n)=>e in t?p(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,m=(t,e)=>{for(var n in e||(e={}))D.call(e,n)&&s(t,n,e[n]);if(c)for(var n of c(e))F.call(e,n)&&s(t,n,e[n]);return t},h=(t,e)=>V(t,b(e)),o=(t,e)=>p(t,"name",{value:e,configurable:!0});var _react = require('react'); var _react2 = _interopRequireDefault(_react);var g,f=typeof process!="undefined"&&((g=process.env)==null?void 0:g.NODE_ENV)!=="production";function x(t){return typeof t=="function"}o(x,"isRenderFn");function R(t,e,n,r){if(r===void 0)return e;if(typeof r=="function")return r(t,e,n);let i=t[r];return i==null?(f&&console.warn(`RenderList: keyBy="${String(r)}" but the field is undefined in ${JSON.stringify(t)}`),e):i}o(R,"getKey");function y({items:t,render:e,keyBy:n}){return _react2.default.createElement(_react2.default.Fragment,null,t.map((r,i)=>{let l=R(r,i,t,n);if(x(e))return _react2.default.createElement(_react2.default.Fragment,{key:l},e(r,i,t));let{component:u,dataKey:a="item",props:w={}}=e,M=h(m({},w),{[a]:r});return _react2.default.createElement(_react2.default.Fragment,{key:l},_react2.default.createElement(u,M))}))}o(y,"RenderList");function N({when:t,children:e}){let n=_react.Children.toArray(e);return n.length===0?null:(n.length>2&&f&&console.warn(`RenderIf: Expected at most 2 children, but got ${n.length}. Only the first 2 children will be used.`),n.length===1?t?n[0]:null:t?n[0]:n[1])}o(N,"RenderIf");var T=N;function I(t,e){for(let n=0;n<e.length;n++){let r=e[n];if(typeof r=="string"){if(r===t)return n}else if(r.includes(t))return n}return-1}o(I,"findMatchIndex");function C(t){let e=[];for(let n of t)typeof n=="string"?e.push(n):e.push(...n);return e}o(C,"getAllValues");function O({value:t,items:e,children:n}){var l;let r=I(t,e);if(r===-1){if(f){let u=C(e);console.warn(`RenderMatch: Value "${t}" not found in any of the items. Available values: [${u.join(", ")}]`)}return null}let i=_react.Children.toArray(n).filter(u=>_react.isValidElement.call(void 0, u));return r>=i.length?(f&&console.warn(`RenderMatch: Not enough children provided. Expected at least ${r+1}, but got ${i.length}.`),null):(l=i[r])!=null?l:null}o(O,"RenderMatch");var j=O;function E(t){for(let e=0;e<t.length;e++)if(t[e])return e;return-1}o(E,"findTrueCaseIndex");function v(t){let e=[];for(let n=0;n<t.length;n++)t[n]&&e.push(n);return e}o(v,"findAllTrueCaseIndices");function A(t,e,n){f&&t>e&&console.warn(`${n}: More cases (${t}) than children (${e}). Extra cases will be ignored.`)}o(A,"validateCasesLength");function _({cases:t,children:e,fallback:n=null,multiple:r=!1}){let i=_react.Children.toArray(e).filter(l=>_react.isValidElement.call(void 0, l));if(A(t.length,i.length,"RenderSwitch"),r){let u=v(t).filter(a=>a>=0&&a<i.length).map(a=>i[a]);if(u.length>0)return _react2.default.createElement(_react2.default.Fragment,null,u)}else{let l=E(t);if(l>=0&&l<i.length)return i[l]}return n}o(_,"RenderSwitch");var k=_;exports.RenderIf = T; exports.RenderList = y; exports.RenderMatch = j; exports.RenderSwitch = k;
2
2
  //# sourceMappingURL=main.cjs.js.map
package/dist/main.d.mts CHANGED
@@ -156,9 +156,12 @@ declare function RenderMatch<T extends string = string>({ value, items, children
156
156
  interface RenderSwitchProps {
157
157
  /**
158
158
  * Array of boolean conditions to match against children
159
- * - The first true condition determines which child to render
159
+ * - By default (multiple=false), only the first true condition's child is rendered
160
+ * - When multiple=true, all true conditions' corresponding children will be rendered
160
161
  * @example [true, false, false] renders the first child
161
162
  * @example [false, true, false] renders the second child
163
+ * @example [true, true, false] renders first child only (default)
164
+ * @example [true, true, false] renders first and second children (when multiple=true)
162
165
  */
163
166
  cases: readonly boolean[];
164
167
  /**
@@ -173,21 +176,40 @@ interface RenderSwitchProps {
173
176
  * @default null
174
177
  */
175
178
  fallback?: ReactNode;
179
+ /**
180
+ * If true, render all matching children
181
+ * If false (default), only render the first matching child
182
+ * @default false
183
+ */
184
+ multiple?: boolean;
176
185
  }
177
186
 
178
187
  /**
179
188
  * RenderSwitch - Switch-style conditional rendering
180
189
  *
181
- * Renders the first child whose corresponding case condition is true.
190
+ * By `default` (multiple=false), renders only the first matching child.
191
+ * When multiple=true, renders all children whose corresponding case conditions are true.
182
192
  * If none matches, renders `fallback` (or null if not provided).
183
193
  *
184
- * @example Basic usage
194
+ * @example Basic usage - render only first match
185
195
  * ```tsx
186
196
  * <RenderSwitch cases={[isLoading, isError, isSuccess]}>
187
197
  * <LoadingSpinner />
188
198
  * <ErrorDisplay />
189
199
  * <SuccessMessage />
190
200
  * </RenderSwitch>
201
+ * // Only renders the first matching child
202
+ * ```
203
+ *
204
+ * @example With multiple - render all matches
205
+ * ```tsx
206
+ * <RenderSwitch cases={[hasRead, hasWrite, hasDelete]} multiple>
207
+ * <ReadPermission />
208
+ * <WritePermission />
209
+ * <DeletePermission />
210
+ * </RenderSwitch>
211
+ * // If hasRead=true, hasWrite=true, hasDelete=false,
212
+ * // renders both ReadPermission and WritePermission
191
213
  * ```
192
214
  *
193
215
  * @example With fallback
@@ -201,6 +223,6 @@ interface RenderSwitchProps {
201
223
  * </RenderSwitch>
202
224
  * ```
203
225
  */
204
- declare function RenderSwitch({ cases, children, fallback, }: RenderSwitchProps): string | number | boolean | ReactElement<any, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null;
226
+ declare function RenderSwitch({ cases, children, fallback, multiple, }: RenderSwitchProps): string | number | boolean | Iterable<react__default.ReactNode> | react__default.JSX.Element | null;
205
227
 
206
228
  export { type KeyBy, type MatchValue, type RenderComponentConfig, type RenderFn, RenderIf, type RenderIfProps, RenderList, type RenderListProps, RenderMatch, type RenderMatchProps, type RenderProp, RenderSwitch, type RenderSwitchProps };
package/dist/main.d.ts CHANGED
@@ -156,9 +156,12 @@ declare function RenderMatch<T extends string = string>({ value, items, children
156
156
  interface RenderSwitchProps {
157
157
  /**
158
158
  * Array of boolean conditions to match against children
159
- * - The first true condition determines which child to render
159
+ * - By default (multiple=false), only the first true condition's child is rendered
160
+ * - When multiple=true, all true conditions' corresponding children will be rendered
160
161
  * @example [true, false, false] renders the first child
161
162
  * @example [false, true, false] renders the second child
163
+ * @example [true, true, false] renders first child only (default)
164
+ * @example [true, true, false] renders first and second children (when multiple=true)
162
165
  */
163
166
  cases: readonly boolean[];
164
167
  /**
@@ -173,21 +176,40 @@ interface RenderSwitchProps {
173
176
  * @default null
174
177
  */
175
178
  fallback?: ReactNode;
179
+ /**
180
+ * If true, render all matching children
181
+ * If false (default), only render the first matching child
182
+ * @default false
183
+ */
184
+ multiple?: boolean;
176
185
  }
177
186
 
178
187
  /**
179
188
  * RenderSwitch - Switch-style conditional rendering
180
189
  *
181
- * Renders the first child whose corresponding case condition is true.
190
+ * By `default` (multiple=false), renders only the first matching child.
191
+ * When multiple=true, renders all children whose corresponding case conditions are true.
182
192
  * If none matches, renders `fallback` (or null if not provided).
183
193
  *
184
- * @example Basic usage
194
+ * @example Basic usage - render only first match
185
195
  * ```tsx
186
196
  * <RenderSwitch cases={[isLoading, isError, isSuccess]}>
187
197
  * <LoadingSpinner />
188
198
  * <ErrorDisplay />
189
199
  * <SuccessMessage />
190
200
  * </RenderSwitch>
201
+ * // Only renders the first matching child
202
+ * ```
203
+ *
204
+ * @example With multiple - render all matches
205
+ * ```tsx
206
+ * <RenderSwitch cases={[hasRead, hasWrite, hasDelete]} multiple>
207
+ * <ReadPermission />
208
+ * <WritePermission />
209
+ * <DeletePermission />
210
+ * </RenderSwitch>
211
+ * // If hasRead=true, hasWrite=true, hasDelete=false,
212
+ * // renders both ReadPermission and WritePermission
191
213
  * ```
192
214
  *
193
215
  * @example With fallback
@@ -201,6 +223,6 @@ interface RenderSwitchProps {
201
223
  * </RenderSwitch>
202
224
  * ```
203
225
  */
204
- declare function RenderSwitch({ cases, children, fallback, }: RenderSwitchProps): string | number | boolean | ReactElement<any, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null;
226
+ declare function RenderSwitch({ cases, children, fallback, multiple, }: RenderSwitchProps): string | number | boolean | Iterable<react__default.ReactNode> | react__default.JSX.Element | null;
205
227
 
206
228
  export { type KeyBy, type MatchValue, type RenderComponentConfig, type RenderFn, RenderIf, type RenderIfProps, RenderList, type RenderListProps, RenderMatch, type RenderMatchProps, type RenderProp, RenderSwitch, type RenderSwitchProps };
package/dist/main.esm.js CHANGED
@@ -1,2 +1,2 @@
1
- var c=Object.defineProperty,A=Object.defineProperties;var M=Object.getOwnPropertyDescriptors;var d=Object.getOwnPropertySymbols;var V=Object.prototype.hasOwnProperty,b=Object.prototype.propertyIsEnumerable;var s=(t,e,n)=>e in t?c(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,p=(t,e)=>{for(var n in e||(e={}))V.call(e,n)&&s(t,n,e[n]);if(d)for(var n of d(e))b.call(e,n)&&s(t,n,e[n]);return t},m=(t,e)=>A(t,M(e)),o=(t,e)=>c(t,"name",{value:e,configurable:!0});import u from"react";var h,l=typeof process!="undefined"&&((h=process.env)==null?void 0:h.NODE_ENV)!=="production";function g(t){return typeof t=="function"}o(g,"isRenderFn");function x(t,e,n,r){if(r===void 0)return e;if(typeof r=="function")return r(t,e,n);let i=t[r];return i==null?(l&&console.warn(`RenderList: keyBy="${String(r)}" but the field is undefined in ${JSON.stringify(t)}`),e):i}o(x,"getKey");function R({items:t,render:e,keyBy:n}){return u.createElement(u.Fragment,null,t.map((r,i)=>{let f=x(r,i,t,n);if(g(e))return u.createElement(u.Fragment,{key:f},e(r,i,t));let{component:a,dataKey:w="item",props:C={}}=e,I=m(p({},C),{[w]:r});return u.createElement(u.Fragment,{key:f},u.createElement(a,I))}))}o(R,"RenderList");import{Children as D}from"react";function F({when:t,children:e}){let n=D.toArray(e);return n.length===0?null:(n.length>2&&l&&console.warn(`RenderIf: Expected at most 2 children, but got ${n.length}. Only the first 2 children will be used.`),n.length===1?t?n[0]:null:t?n[0]:n[1])}o(F,"RenderIf");var S=F;import{Children as N,isValidElement as K}from"react";function y(t,e){for(let n=0;n<e.length;n++){let r=e[n];if(typeof r=="string"){if(r===t)return n}else if(r.includes(t))return n}return-1}o(y,"findMatchIndex");function v(t){let e=[];for(let n of t)typeof n=="string"?e.push(n):e.push(...n);return e}o(v,"getAllValues");function L({value:t,items:e,children:n}){var f;let r=y(t,e);if(r===-1){if(l){let a=v(e);console.warn(`RenderMatch: Value "${t}" not found in any of the items. Available values: [${a.join(", ")}]`)}return null}let i=N.toArray(n).filter(a=>K(a));return r>=i.length?(l&&console.warn(`RenderMatch: Not enough children provided. Expected at least ${r+1}, but got ${i.length}.`),null):(f=i[r])!=null?f:null}o(L,"RenderMatch");var O=L;import{Children as T,isValidElement as j}from"react";function E(t){for(let e=0;e<t.length;e++)if(t[e])return e;return-1}o(E,"findTrueCaseIndex");function $(t,e,n){l&&t>e&&console.warn(`${n}: More cases (${t}) than children (${e}). Extra cases will be ignored.`)}o($,"validateCasesLength");function J({cases:t,children:e,fallback:n=null}){let r=T.toArray(e).filter(f=>j(f));$(t.length,r.length,"RenderSwitch");let i=E(t);return i>=0&&i<r.length?r[i]:n}o(J,"RenderSwitch");var P=J;export{S as RenderIf,R as RenderList,O as RenderMatch,P as RenderSwitch};
1
+ var p=Object.defineProperty,V=Object.defineProperties;var b=Object.getOwnPropertyDescriptors;var c=Object.getOwnPropertySymbols;var D=Object.prototype.hasOwnProperty,F=Object.prototype.propertyIsEnumerable;var s=(t,e,n)=>e in t?p(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,m=(t,e)=>{for(var n in e||(e={}))D.call(e,n)&&s(t,n,e[n]);if(c)for(var n of c(e))F.call(e,n)&&s(t,n,e[n]);return t},h=(t,e)=>V(t,b(e)),o=(t,e)=>p(t,"name",{value:e,configurable:!0});import d from"react";var g,f=typeof process!="undefined"&&((g=process.env)==null?void 0:g.NODE_ENV)!=="production";function x(t){return typeof t=="function"}o(x,"isRenderFn");function R(t,e,n,r){if(r===void 0)return e;if(typeof r=="function")return r(t,e,n);let i=t[r];return i==null?(f&&console.warn(`RenderList: keyBy="${String(r)}" but the field is undefined in ${JSON.stringify(t)}`),e):i}o(R,"getKey");function y({items:t,render:e,keyBy:n}){return d.createElement(d.Fragment,null,t.map((r,i)=>{let l=R(r,i,t,n);if(x(e))return d.createElement(d.Fragment,{key:l},e(r,i,t));let{component:u,dataKey:a="item",props:w={}}=e,M=h(m({},w),{[a]:r});return d.createElement(d.Fragment,{key:l},d.createElement(u,M))}))}o(y,"RenderList");import{Children as S}from"react";function N({when:t,children:e}){let n=S.toArray(e);return n.length===0?null:(n.length>2&&f&&console.warn(`RenderIf: Expected at most 2 children, but got ${n.length}. Only the first 2 children will be used.`),n.length===1?t?n[0]:null:t?n[0]:n[1])}o(N,"RenderIf");var T=N;import{Children as K,isValidElement as L}from"react";function I(t,e){for(let n=0;n<e.length;n++){let r=e[n];if(typeof r=="string"){if(r===t)return n}else if(r.includes(t))return n}return-1}o(I,"findMatchIndex");function C(t){let e=[];for(let n of t)typeof n=="string"?e.push(n):e.push(...n);return e}o(C,"getAllValues");function O({value:t,items:e,children:n}){var l;let r=I(t,e);if(r===-1){if(f){let u=C(e);console.warn(`RenderMatch: Value "${t}" not found in any of the items. Available values: [${u.join(", ")}]`)}return null}let i=K.toArray(n).filter(u=>L(u));return r>=i.length?(f&&console.warn(`RenderMatch: Not enough children provided. Expected at least ${r+1}, but got ${i.length}.`),null):(l=i[r])!=null?l:null}o(O,"RenderMatch");var j=O;import{Children as J,isValidElement as P}from"react";function E(t){for(let e=0;e<t.length;e++)if(t[e])return e;return-1}o(E,"findTrueCaseIndex");function v(t){let e=[];for(let n=0;n<t.length;n++)t[n]&&e.push(n);return e}o(v,"findAllTrueCaseIndices");function A(t,e,n){f&&t>e&&console.warn(`${n}: More cases (${t}) than children (${e}). Extra cases will be ignored.`)}o(A,"validateCasesLength");import $ from"react";function _({cases:t,children:e,fallback:n=null,multiple:r=!1}){let i=J.toArray(e).filter(l=>P(l));if(A(t.length,i.length,"RenderSwitch"),r){let u=v(t).filter(a=>a>=0&&a<i.length).map(a=>i[a]);if(u.length>0)return $.createElement($.Fragment,null,u)}else{let l=E(t);if(l>=0&&l<i.length)return i[l]}return n}o(_,"RenderSwitch");var k=_;export{T as RenderIf,y as RenderList,j as RenderMatch,k as RenderSwitch};
2
2
  //# sourceMappingURL=main.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/render-list/index.tsx","../src/shared/env.ts","../src/render-list/render-list.utils.ts","../src/render-if/index.tsx","../src/render-match/index.tsx","../src/render-match/render-match.utils.ts","../src/render-switch/index.tsx","../src/render-switch/render-switch.utils.ts"],"sourcesContent":["import React from 'react';\nimport type { RenderListProps } from './render-list.type';\nimport { isRenderFn, getKey } from './render-list.utils';\n\n/**\n * RenderList - Recommended list component\n *\n * @example Function style\n * ```tsx\n * <RenderList\n * items={users}\n * render={(user) => <UserCard user={user} />}\n * keyBy=\"id\"\n * />\n * ```\n *\n * @example Component style\n * ```tsx\n * <RenderList\n * items={users}\n * render={{\n * component: UserCard,\n * dataKey: \"user\",\n * props: { variant: 'compact' }\n * }}\n * keyBy=\"id\"\n * />\n * ```\n */\nexport default function RenderList<T>({ items, render, keyBy }: RenderListProps<T>) {\n return (\n <>\n {items.map((item, index) => {\n const key = getKey(item, index, items, keyBy);\n\n // If render is a function, call it directly\n if (isRenderFn(render)) {\n return <React.Fragment key={key}>{render(item, index, items)}</React.Fragment>;\n }\n\n // If render is component config, wrap props automatically\n const { component: Component, dataKey = 'item', props = {} } = render;\n const componentProps = {\n ...props,\n [dataKey]: item,\n };\n\n return (\n <React.Fragment key={key}>\n <Component {...componentProps} />\n </React.Fragment>\n );\n })}\n </>\n );\n}\n","/**\n * Check if running in development mode\n */\nexport const isDev =\n typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';\n\n","import type { RenderProp, RenderFn, KeyBy } from './render-list.type';\nimport { isDev } from '../shared/env';\n\n/**\n * Type guard: check if render is a function type\n */\nexport function isRenderFn<T>(render: RenderProp<T>): render is RenderFn<T> {\n return typeof render === 'function';\n}\n\n/**\n * Get the unique key for a list item\n * @param item The list item\n * @param index The index of the item in the list\n * @param items The list of items\n * @param keyBy The keyBy function or field name to get the key from the item\n */\nexport function getKey<T>(\n item: T,\n index: number,\n items: readonly T[],\n keyBy: KeyBy<T> | undefined,\n): string | number {\n if (keyBy === undefined) {\n return index;\n }\n\n if (typeof keyBy === 'function') {\n return keyBy(item, index, items);\n }\n\n const value = (item as Record<string, unknown>)[keyBy as string];\n if (value === undefined || value === null) {\n if (isDev) {\n console.warn(\n `RenderList: keyBy=\"${String(keyBy)}\" but the field is undefined in ${JSON.stringify(item)}`,\n );\n }\n return index;\n }\n\n return value as string | number;\n}\n","import { Children } from 'react';\nimport type { RenderIfProps } from './render-if.type';\nimport { isDev } from '../shared/env';\n\n/**\n * RenderIf - Conditional rendering component\n *\n * @example Single child (render when true, nothing when false)\n * ```tsx\n * <RenderIf when={isLoggedIn}>\n * <Dashboard />\n * </RenderIf>\n * ```\n *\n * @example Two children (if/else pattern)\n * ```tsx\n * <RenderIf when={isLoggedIn}>\n * <Dashboard />\n * <Login />\n * </RenderIf>\n * ```\n */\nexport function RenderIf({ when, children }: RenderIfProps) {\n const childArray = Children.toArray(children);\n\n if (childArray.length === 0) {\n return null;\n }\n\n if (childArray.length > 2) {\n if (isDev) {\n console.warn(\n `RenderIf: Expected at most 2 children, but got ${childArray.length}. Only the first 2 children will be used.`\n );\n }\n }\n\n if (childArray.length === 1) {\n return when ? childArray[0] : null;\n }\n\n // length >= 2: first child for true, second for false\n return when ? childArray[0] : childArray[1];\n}\n\nexport default RenderIf;\n","import { Children, isValidElement, type ReactElement } from 'react';\nimport type { RenderMatchProps } from './render-match.type';\nimport { findMatchIndex, getAllValues } from './render-match.utils';\nimport { isDev } from '../shared/env';\n\n/**\n * RenderMatch - Match value against items and render corresponding child\n *\n * @example Basic usage\n * ```tsx\n * <RenderMatch value=\"success\" items={['pending', 'success', 'error']}>\n * <PendingState />\n * <SuccessState />\n * <ErrorState />\n * </RenderMatch>\n * ```\n *\n * @example With array values (multiple values map to same child)\n * ```tsx\n * <RenderMatch\n * value=\"processing\"\n * items={[['pending', 'processing'], 'success', 'error']}\n * >\n * <LoadingState />\n * <SuccessState />\n * <ErrorState />\n * </RenderMatch>\n * ```\n */\nexport function RenderMatch<T extends string = string>({\n value,\n items,\n children,\n}: RenderMatchProps<T>) {\n // Find the matched slot index\n const matchedIndex = findMatchIndex(value, items);\n\n if (matchedIndex === -1) {\n if (isDev) {\n const allValues = getAllValues(items);\n console.warn(\n `RenderMatch: Value \"${value}\" not found in any of the items. Available values: [${allValues.join(', ')}]`\n );\n }\n return null;\n }\n\n const validChildren = Children.toArray(children).filter(\n (child): child is ReactElement => isValidElement(child)\n );\n\n if (matchedIndex >= validChildren.length) {\n if (isDev) {\n console.warn(\n `RenderMatch: Not enough children provided. Expected at least ${matchedIndex + 1}, but got ${validChildren.length}.`\n );\n }\n return null;\n }\n\n return validChildren[matchedIndex] ?? null;\n}\n\nexport default RenderMatch;\n","import type { MatchValue } from './render-match.type';\n\n/**\n * Find the index of the item that matches the value\n * @param items The items to search in\n * @param value The value to match\n * @returns The matched index, or -1 if not found\n */\nexport function findMatchIndex(\n value: string,\n items: readonly MatchValue[]\n): number {\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (typeof item === 'string') {\n if (item === value) {\n return i;\n }\n } else {\n // item is string[]\n if (item.includes(value)) {\n return i;\n }\n }\n }\n return -1;\n}\n\n/**\n * Get all possible values from items (flatten string arrays)\n * @param items The items to get values from\n * @returns The flattened string array of all values\n */\nexport function getAllValues(items: readonly MatchValue[]): string[] {\n const result: string[] = [];\n for (const item of items) {\n if (typeof item === 'string') {\n result.push(item);\n } else {\n result.push(...item);\n }\n }\n return result;\n}\n","import { Children, isValidElement, type ReactElement } from 'react';\nimport type { RenderSwitchProps } from './render-switch.type';\nimport { findTrueCaseIndex, validateCasesLength } from './render-switch.utils';\n\n/**\n * RenderSwitch - Switch-style conditional rendering\n *\n * Renders the first child whose corresponding case condition is true.\n * If none matches, renders `fallback` (or null if not provided).\n *\n * @example Basic usage\n * ```tsx\n * <RenderSwitch cases={[isLoading, isError, isSuccess]}>\n * <LoadingSpinner />\n * <ErrorDisplay />\n * <SuccessMessage />\n * </RenderSwitch>\n * ```\n *\n * @example With fallback\n * ```tsx\n * <RenderSwitch\n * cases={[isAdmin, isModerator]}\n * fallback={<AccessDenied />}\n * >\n * <AdminPanel />\n * <ModeratorPanel />\n * </RenderSwitch>\n * ```\n */\nexport function RenderSwitch({\n cases,\n children,\n fallback = null,\n}: RenderSwitchProps) {\n const childArray = Children.toArray(children).filter(\n (child): child is ReactElement => isValidElement(child)\n );\n\n validateCasesLength(cases.length, childArray.length, 'RenderSwitch');\n\n const matchedIndex = findTrueCaseIndex(cases);\n\n // Check if the matched index is within the children bounds\n if (matchedIndex >= 0 && matchedIndex < childArray.length) {\n return childArray[matchedIndex];\n }\n\n return fallback;\n}\n\nexport default RenderSwitch;\n","import { isDev } from '../shared/env';\n\n/**\n * Find the index of the first true case\n * @param cases An array of boolean values\n * @returns The index of the first true case, or -1 if none are true\n */\nexport function findTrueCaseIndex(cases: readonly boolean[]): number {\n for (let i = 0; i < cases.length; i++) {\n if (cases[i]) {\n return i;\n }\n }\n return -1;\n}\n\n/**\n * Validate that the number of cases matches the number of children\n * @param casesLength The number of cases\n * @param childrenLength The number of children\n * @param componentName The name of the component\n * @throws An error if the number of cases is greater than the number of children\n * @returns void\n */\nexport function validateCasesLength(\n casesLength: number,\n childrenLength: number,\n componentName: string\n): void {\n if (isDev && casesLength > childrenLength) {\n console.warn(\n `${componentName}: More cases (${casesLength}) than children (${childrenLength}). Extra cases will be ignored.`\n );\n }\n}\n"],"mappings":"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","names":["React","_a","isDev","process","env","NODE_ENV","isRenderFn","render","getKey","item","index","items","keyBy","undefined","value","isDev","console","warn","String","JSON","stringify","RenderList","items","render","keyBy","React","map","item","index","key","getKey","isRenderFn","Fragment","component","Component","dataKey","props","componentProps","__spreadProps","__spreadValues","Children","RenderIf","when","children","childArray","Children","toArray","length","isDev","console","warn","render_if_default","Children","isValidElement","findMatchIndex","value","items","i","length","item","includes","getAllValues","result","push","RenderMatch","value","items","children","_a","matchedIndex","findMatchIndex","isDev","allValues","getAllValues","console","warn","join","validChildren","Children","toArray","filter","child","isValidElement","length","render_match_default","Children","isValidElement","findTrueCaseIndex","cases","i","length","validateCasesLength","casesLength","childrenLength","componentName","isDev","console","warn","RenderSwitch","cases","children","fallback","childArray","Children","toArray","filter","child","isValidElement","validateCasesLength","length","matchedIndex","findTrueCaseIndex","render_switch_default"]}
1
+ {"version":3,"sources":["../src/render-list/index.tsx","../src/shared/env.ts","../src/render-list/render-list.utils.ts","../src/render-if/index.tsx","../src/render-match/index.tsx","../src/render-match/render-match.utils.ts","../src/render-switch/index.tsx","../src/render-switch/render-switch.utils.ts"],"sourcesContent":["import React from 'react';\nimport type { RenderListProps } from './render-list.type';\nimport { isRenderFn, getKey } from './render-list.utils';\n\n/**\n * RenderList - Recommended list component\n *\n * @example Function style\n * ```tsx\n * <RenderList\n * items={users}\n * render={(user) => <UserCard user={user} />}\n * keyBy=\"id\"\n * />\n * ```\n *\n * @example Component style\n * ```tsx\n * <RenderList\n * items={users}\n * render={{\n * component: UserCard,\n * dataKey: \"user\",\n * props: { variant: 'compact' }\n * }}\n * keyBy=\"id\"\n * />\n * ```\n */\nexport default function RenderList<T>({ items, render, keyBy }: RenderListProps<T>) {\n return (\n <>\n {items.map((item, index) => {\n const key = getKey(item, index, items, keyBy);\n\n // If render is a function, call it directly\n if (isRenderFn(render)) {\n return <React.Fragment key={key}>{render(item, index, items)}</React.Fragment>;\n }\n\n // If render is component config, wrap props automatically\n const { component: Component, dataKey = 'item', props = {} } = render;\n const componentProps = {\n ...props,\n [dataKey]: item,\n };\n\n return (\n <React.Fragment key={key}>\n <Component {...componentProps} />\n </React.Fragment>\n );\n })}\n </>\n );\n}\n","/**\n * Check if running in development mode\n */\nexport const isDev =\n typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';\n\n","import type { RenderProp, RenderFn, KeyBy } from './render-list.type';\nimport { isDev } from '../shared/env';\n\n/**\n * Type guard: check if render is a function type\n */\nexport function isRenderFn<T>(render: RenderProp<T>): render is RenderFn<T> {\n return typeof render === 'function';\n}\n\n/**\n * Get the unique key for a list item\n * @param item The list item\n * @param index The index of the item in the list\n * @param items The list of items\n * @param keyBy The keyBy function or field name to get the key from the item\n */\nexport function getKey<T>(\n item: T,\n index: number,\n items: readonly T[],\n keyBy: KeyBy<T> | undefined,\n): string | number {\n if (keyBy === undefined) {\n return index;\n }\n\n if (typeof keyBy === 'function') {\n return keyBy(item, index, items);\n }\n\n const value = (item as Record<string, unknown>)[keyBy as string];\n if (value === undefined || value === null) {\n if (isDev) {\n console.warn(\n `RenderList: keyBy=\"${String(keyBy)}\" but the field is undefined in ${JSON.stringify(item)}`,\n );\n }\n return index;\n }\n\n return value as string | number;\n}\n","import { Children } from 'react';\nimport type { RenderIfProps } from './render-if.type';\nimport { isDev } from '../shared/env';\n\n/**\n * RenderIf - Conditional rendering component\n *\n * @example Single child (render when true, nothing when false)\n * ```tsx\n * <RenderIf when={isLoggedIn}>\n * <Dashboard />\n * </RenderIf>\n * ```\n *\n * @example Two children (if/else pattern)\n * ```tsx\n * <RenderIf when={isLoggedIn}>\n * <Dashboard />\n * <Login />\n * </RenderIf>\n * ```\n */\nexport function RenderIf({ when, children }: RenderIfProps) {\n const childArray = Children.toArray(children);\n\n if (childArray.length === 0) {\n return null;\n }\n\n if (childArray.length > 2) {\n if (isDev) {\n console.warn(\n `RenderIf: Expected at most 2 children, but got ${childArray.length}. Only the first 2 children will be used.`\n );\n }\n }\n\n if (childArray.length === 1) {\n return when ? childArray[0] : null;\n }\n\n // length >= 2: first child for true, second for false\n return when ? childArray[0] : childArray[1];\n}\n\nexport default RenderIf;\n","import { Children, isValidElement, type ReactElement } from 'react';\nimport type { RenderMatchProps } from './render-match.type';\nimport { findMatchIndex, getAllValues } from './render-match.utils';\nimport { isDev } from '../shared/env';\n\n/**\n * RenderMatch - Match value against items and render corresponding child\n *\n * @example Basic usage\n * ```tsx\n * <RenderMatch value=\"success\" items={['pending', 'success', 'error']}>\n * <PendingState />\n * <SuccessState />\n * <ErrorState />\n * </RenderMatch>\n * ```\n *\n * @example With array values (multiple values map to same child)\n * ```tsx\n * <RenderMatch\n * value=\"processing\"\n * items={[['pending', 'processing'], 'success', 'error']}\n * >\n * <LoadingState />\n * <SuccessState />\n * <ErrorState />\n * </RenderMatch>\n * ```\n */\nexport function RenderMatch<T extends string = string>({\n value,\n items,\n children,\n}: RenderMatchProps<T>) {\n // Find the matched slot index\n const matchedIndex = findMatchIndex(value, items);\n\n if (matchedIndex === -1) {\n if (isDev) {\n const allValues = getAllValues(items);\n console.warn(\n `RenderMatch: Value \"${value}\" not found in any of the items. Available values: [${allValues.join(', ')}]`\n );\n }\n return null;\n }\n\n const validChildren = Children.toArray(children).filter(\n (child): child is ReactElement => isValidElement(child)\n );\n\n if (matchedIndex >= validChildren.length) {\n if (isDev) {\n console.warn(\n `RenderMatch: Not enough children provided. Expected at least ${matchedIndex + 1}, but got ${validChildren.length}.`\n );\n }\n return null;\n }\n\n return validChildren[matchedIndex] ?? null;\n}\n\nexport default RenderMatch;\n","import type { MatchValue } from './render-match.type';\n\n/**\n * Find the index of the item that matches the value\n * @param items The items to search in\n * @param value The value to match\n * @returns The matched index, or -1 if not found\n */\nexport function findMatchIndex(\n value: string,\n items: readonly MatchValue[]\n): number {\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (typeof item === 'string') {\n if (item === value) {\n return i;\n }\n } else {\n // item is string[]\n if (item.includes(value)) {\n return i;\n }\n }\n }\n return -1;\n}\n\n/**\n * Get all possible values from items (flatten string arrays)\n * @param items The items to get values from\n * @returns The flattened string array of all values\n */\nexport function getAllValues(items: readonly MatchValue[]): string[] {\n const result: string[] = [];\n for (const item of items) {\n if (typeof item === 'string') {\n result.push(item);\n } else {\n result.push(...item);\n }\n }\n return result;\n}\n","import { Children, isValidElement, type ReactElement } from 'react';\nimport type { RenderSwitchProps } from './render-switch.type';\nimport { findTrueCaseIndex, findAllTrueCaseIndices, validateCasesLength } from './render-switch.utils';\nimport React from 'react';\n\n/**\n * RenderSwitch - Switch-style conditional rendering\n *\n * By `default` (multiple=false), renders only the first matching child.\n * When multiple=true, renders all children whose corresponding case conditions are true.\n * If none matches, renders `fallback` (or null if not provided).\n *\n * @example Basic usage - render only first match\n * ```tsx\n * <RenderSwitch cases={[isLoading, isError, isSuccess]}>\n * <LoadingSpinner />\n * <ErrorDisplay />\n * <SuccessMessage />\n * </RenderSwitch>\n * // Only renders the first matching child\n * ```\n *\n * @example With multiple - render all matches\n * ```tsx\n * <RenderSwitch cases={[hasRead, hasWrite, hasDelete]} multiple>\n * <ReadPermission />\n * <WritePermission />\n * <DeletePermission />\n * </RenderSwitch>\n * // If hasRead=true, hasWrite=true, hasDelete=false,\n * // renders both ReadPermission and WritePermission\n * ```\n *\n * @example With fallback\n * ```tsx\n * <RenderSwitch\n * cases={[isAdmin, isModerator]}\n * fallback={<AccessDenied />}\n * >\n * <AdminPanel />\n * <ModeratorPanel />\n * </RenderSwitch>\n * ```\n */\nexport function RenderSwitch({\n cases,\n children,\n fallback = null,\n multiple = false,\n}: RenderSwitchProps) {\n const childArray = Children.toArray(children).filter(\n (child): child is ReactElement => isValidElement(child)\n );\n\n validateCasesLength(cases.length, childArray.length, 'RenderSwitch');\n\n if (multiple) {\n // Render all matches\n const matchedIndices = findAllTrueCaseIndices(cases);\n const matchedChildren = matchedIndices\n .filter(index => index >= 0 && index < childArray.length)\n .map(index => childArray[index]);\n\n if (matchedChildren.length > 0) {\n return <>{matchedChildren}</>;\n }\n } else {\n // Default behavior: only render first match\n const matchedIndex = findTrueCaseIndex(cases);\n\n if (matchedIndex >= 0 && matchedIndex < childArray.length) {\n return childArray[matchedIndex];\n }\n }\n\n return fallback;\n}\n\nexport default RenderSwitch;\n","import { isDev } from '../shared/env';\n\n/**\n * Find the index of the first true case\n * @param cases An array of boolean values\n * @returns The index of the first true case, or -1 if none are true\n */\nexport function findTrueCaseIndex(cases: readonly boolean[]): number {\n for (let i = 0; i < cases.length; i++) {\n if (cases[i]) {\n return i;\n }\n }\n return -1;\n}\n\n/**\n * Find all indices of true cases\n * @param cases An array of boolean values\n * @returns An array of indices where cases are true\n */\nexport function findAllTrueCaseIndices(cases: readonly boolean[]): number[] {\n const indices: number[] = [];\n for (let i = 0; i < cases.length; i++) {\n if (cases[i]) {\n indices.push(i);\n }\n }\n return indices;\n}\n\n/**\n * Validate that the number of cases matches the number of children\n * @param casesLength The number of cases\n * @param childrenLength The number of children\n * @param componentName The name of the component\n * @throws An error if the number of cases is greater than the number of children\n * @returns void\n */\nexport function validateCasesLength(\n casesLength: number,\n childrenLength: number,\n componentName: string\n): void {\n if (isDev && casesLength > childrenLength) {\n console.warn(\n `${componentName}: More cases (${casesLength}) than children (${childrenLength}). Extra cases will be ignored.`\n );\n }\n}\n"],"mappings":"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","names":["React","_a","isDev","process","env","NODE_ENV","isRenderFn","render","getKey","item","index","items","keyBy","undefined","value","isDev","console","warn","String","JSON","stringify","RenderList","items","render","keyBy","React","map","item","index","key","getKey","isRenderFn","Fragment","component","Component","dataKey","props","componentProps","__spreadProps","__spreadValues","Children","RenderIf","when","children","childArray","Children","toArray","length","isDev","console","warn","render_if_default","Children","isValidElement","findMatchIndex","value","items","i","length","item","includes","getAllValues","result","push","RenderMatch","value","items","children","_a","matchedIndex","findMatchIndex","isDev","allValues","getAllValues","console","warn","join","validChildren","Children","toArray","filter","child","isValidElement","length","render_match_default","Children","isValidElement","findTrueCaseIndex","cases","i","length","findAllTrueCaseIndices","indices","push","validateCasesLength","casesLength","childrenLength","componentName","isDev","console","warn","React","RenderSwitch","cases","children","fallback","multiple","childArray","Children","toArray","filter","child","isValidElement","validateCasesLength","length","matchedChildren","findAllTrueCaseIndices","index","map","React","matchedIndex","findTrueCaseIndex","render_switch_default"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jswork/react-render-controls",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "main": "dist/main.cjs.js",
5
5
  "module": "dist/main.esm.js",
6
6
  "types": "dist/main.d.ts",
@@ -1,20 +1,34 @@
1
1
  import { Children, isValidElement, type ReactElement } from 'react';
2
2
  import type { RenderSwitchProps } from './render-switch.type';
3
- import { findTrueCaseIndex, validateCasesLength } from './render-switch.utils';
3
+ import { findTrueCaseIndex, findAllTrueCaseIndices, validateCasesLength } from './render-switch.utils';
4
+ import React from 'react';
4
5
 
5
6
  /**
6
7
  * RenderSwitch - Switch-style conditional rendering
7
8
  *
8
- * Renders the first child whose corresponding case condition is true.
9
+ * By `default` (multiple=false), renders only the first matching child.
10
+ * When multiple=true, renders all children whose corresponding case conditions are true.
9
11
  * If none matches, renders `fallback` (or null if not provided).
10
12
  *
11
- * @example Basic usage
13
+ * @example Basic usage - render only first match
12
14
  * ```tsx
13
15
  * <RenderSwitch cases={[isLoading, isError, isSuccess]}>
14
16
  * <LoadingSpinner />
15
17
  * <ErrorDisplay />
16
18
  * <SuccessMessage />
17
19
  * </RenderSwitch>
20
+ * // Only renders the first matching child
21
+ * ```
22
+ *
23
+ * @example With multiple - render all matches
24
+ * ```tsx
25
+ * <RenderSwitch cases={[hasRead, hasWrite, hasDelete]} multiple>
26
+ * <ReadPermission />
27
+ * <WritePermission />
28
+ * <DeletePermission />
29
+ * </RenderSwitch>
30
+ * // If hasRead=true, hasWrite=true, hasDelete=false,
31
+ * // renders both ReadPermission and WritePermission
18
32
  * ```
19
33
  *
20
34
  * @example With fallback
@@ -32,6 +46,7 @@ export function RenderSwitch({
32
46
  cases,
33
47
  children,
34
48
  fallback = null,
49
+ multiple = false,
35
50
  }: RenderSwitchProps) {
36
51
  const childArray = Children.toArray(children).filter(
37
52
  (child): child is ReactElement => isValidElement(child)
@@ -39,11 +54,23 @@ export function RenderSwitch({
39
54
 
40
55
  validateCasesLength(cases.length, childArray.length, 'RenderSwitch');
41
56
 
42
- const matchedIndex = findTrueCaseIndex(cases);
57
+ if (multiple) {
58
+ // Render all matches
59
+ const matchedIndices = findAllTrueCaseIndices(cases);
60
+ const matchedChildren = matchedIndices
61
+ .filter(index => index >= 0 && index < childArray.length)
62
+ .map(index => childArray[index]);
63
+
64
+ if (matchedChildren.length > 0) {
65
+ return <>{matchedChildren}</>;
66
+ }
67
+ } else {
68
+ // Default behavior: only render first match
69
+ const matchedIndex = findTrueCaseIndex(cases);
43
70
 
44
- // Check if the matched index is within the children bounds
45
- if (matchedIndex >= 0 && matchedIndex < childArray.length) {
46
- return childArray[matchedIndex];
71
+ if (matchedIndex >= 0 && matchedIndex < childArray.length) {
72
+ return childArray[matchedIndex];
73
+ }
47
74
  }
48
75
 
49
76
  return fallback;
@@ -3,9 +3,12 @@ import { type ReactNode } from 'react';
3
3
  export interface RenderSwitchProps {
4
4
  /**
5
5
  * Array of boolean conditions to match against children
6
- * - The first true condition determines which child to render
6
+ * - By default (multiple=false), only the first true condition's child is rendered
7
+ * - When multiple=true, all true conditions' corresponding children will be rendered
7
8
  * @example [true, false, false] renders the first child
8
9
  * @example [false, true, false] renders the second child
10
+ * @example [true, true, false] renders first child only (default)
11
+ * @example [true, true, false] renders first and second children (when multiple=true)
9
12
  */
10
13
  cases: readonly boolean[];
11
14
  /**
@@ -20,4 +23,10 @@ export interface RenderSwitchProps {
20
23
  * @default null
21
24
  */
22
25
  fallback?: ReactNode;
26
+ /**
27
+ * If true, render all matching children
28
+ * If false (default), only render the first matching child
29
+ * @default false
30
+ */
31
+ multiple?: boolean;
23
32
  }
@@ -14,6 +14,21 @@ export function findTrueCaseIndex(cases: readonly boolean[]): number {
14
14
  return -1;
15
15
  }
16
16
 
17
+ /**
18
+ * Find all indices of true cases
19
+ * @param cases An array of boolean values
20
+ * @returns An array of indices where cases are true
21
+ */
22
+ export function findAllTrueCaseIndices(cases: readonly boolean[]): number[] {
23
+ const indices: number[] = [];
24
+ for (let i = 0; i < cases.length; i++) {
25
+ if (cases[i]) {
26
+ indices.push(i);
27
+ }
28
+ }
29
+ return indices;
30
+ }
31
+
17
32
  /**
18
33
  * Validate that the number of cases matches the number of children
19
34
  * @param casesLength The number of cases