@seeqdev/qomponents 0.0.126 → 0.0.128

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 CHANGED
@@ -18978,6 +18978,260 @@ function useSpring(props, deps) {
18978
18978
  );
18979
18979
  return isFn || arguments.length == 2 ? [values, ref] : values;
18980
18980
  }
18981
+ function useTransition(data, props, deps) {
18982
+ const propsFn = is.fun(props) && props;
18983
+ const {
18984
+ reset,
18985
+ sort,
18986
+ trail = 0,
18987
+ expires = true,
18988
+ exitBeforeEnter = false,
18989
+ onDestroyed,
18990
+ ref: propsRef,
18991
+ config: propsConfig
18992
+ } = propsFn ? propsFn() : props;
18993
+ const ref = React.useMemo(
18994
+ () => propsFn || arguments.length == 3 ? SpringRef() : void 0,
18995
+ []
18996
+ );
18997
+ const items = toArray(data);
18998
+ const transitions = [];
18999
+ const usedTransitions = React.useRef(null);
19000
+ const prevTransitions = reset ? null : usedTransitions.current;
19001
+ useIsomorphicLayoutEffect(() => {
19002
+ usedTransitions.current = transitions;
19003
+ });
19004
+ useOnce(() => {
19005
+ each(transitions, (t) => {
19006
+ ref?.add(t.ctrl);
19007
+ t.ctrl.ref = ref;
19008
+ });
19009
+ return () => {
19010
+ each(usedTransitions.current, (t) => {
19011
+ if (t.expired) {
19012
+ clearTimeout(t.expirationId);
19013
+ }
19014
+ detachRefs(t.ctrl, ref);
19015
+ t.ctrl.stop(true);
19016
+ });
19017
+ };
19018
+ });
19019
+ const keys = getKeys(items, propsFn ? propsFn() : props, prevTransitions);
19020
+ const expired = reset && usedTransitions.current || [];
19021
+ useIsomorphicLayoutEffect(
19022
+ () => each(expired, ({ ctrl, item, key }) => {
19023
+ detachRefs(ctrl, ref);
19024
+ callProp(onDestroyed, item, key);
19025
+ })
19026
+ );
19027
+ const reused = [];
19028
+ if (prevTransitions)
19029
+ each(prevTransitions, (t, i) => {
19030
+ if (t.expired) {
19031
+ clearTimeout(t.expirationId);
19032
+ expired.push(t);
19033
+ } else {
19034
+ i = reused[i] = keys.indexOf(t.key);
19035
+ if (~i)
19036
+ transitions[i] = t;
19037
+ }
19038
+ });
19039
+ each(items, (item, i) => {
19040
+ if (!transitions[i]) {
19041
+ transitions[i] = {
19042
+ key: keys[i],
19043
+ item,
19044
+ phase: "mount" /* MOUNT */,
19045
+ ctrl: new Controller()
19046
+ };
19047
+ transitions[i].ctrl.item = item;
19048
+ }
19049
+ });
19050
+ if (reused.length) {
19051
+ let i = -1;
19052
+ const { leave } = propsFn ? propsFn() : props;
19053
+ each(reused, (keyIndex, prevIndex) => {
19054
+ const t = prevTransitions[prevIndex];
19055
+ if (~keyIndex) {
19056
+ i = transitions.indexOf(t);
19057
+ transitions[i] = { ...t, item: items[keyIndex] };
19058
+ } else if (leave) {
19059
+ transitions.splice(++i, 0, t);
19060
+ }
19061
+ });
19062
+ }
19063
+ if (is.fun(sort)) {
19064
+ transitions.sort((a, b) => sort(a.item, b.item));
19065
+ }
19066
+ let delay = -trail;
19067
+ const forceUpdate = useForceUpdate();
19068
+ const defaultProps = getDefaultProps(props);
19069
+ const changes = /* @__PURE__ */ new Map();
19070
+ const exitingTransitions = React.useRef(/* @__PURE__ */ new Map());
19071
+ const forceChange = React.useRef(false);
19072
+ each(transitions, (t, i) => {
19073
+ const key = t.key;
19074
+ const prevPhase = t.phase;
19075
+ const p = propsFn ? propsFn() : props;
19076
+ let to2;
19077
+ let phase;
19078
+ const propsDelay = callProp(p.delay || 0, key);
19079
+ if (prevPhase == "mount" /* MOUNT */) {
19080
+ to2 = p.enter;
19081
+ phase = "enter" /* ENTER */;
19082
+ } else {
19083
+ const isLeave = keys.indexOf(key) < 0;
19084
+ if (prevPhase != "leave" /* LEAVE */) {
19085
+ if (isLeave) {
19086
+ to2 = p.leave;
19087
+ phase = "leave" /* LEAVE */;
19088
+ } else if (to2 = p.update) {
19089
+ phase = "update" /* UPDATE */;
19090
+ } else
19091
+ return;
19092
+ } else if (!isLeave) {
19093
+ to2 = p.enter;
19094
+ phase = "enter" /* ENTER */;
19095
+ } else
19096
+ return;
19097
+ }
19098
+ to2 = callProp(to2, t.item, i);
19099
+ to2 = is.obj(to2) ? inferTo(to2) : { to: to2 };
19100
+ if (!to2.config) {
19101
+ const config2 = propsConfig || defaultProps.config;
19102
+ to2.config = callProp(config2, t.item, i, phase);
19103
+ }
19104
+ delay += trail;
19105
+ const payload = {
19106
+ ...defaultProps,
19107
+ // we need to add our props.delay value you here.
19108
+ delay: propsDelay + delay,
19109
+ ref: propsRef,
19110
+ immediate: p.immediate,
19111
+ // This prevents implied resets.
19112
+ reset: false,
19113
+ // Merge any phase-specific props.
19114
+ ...to2
19115
+ };
19116
+ if (phase == "enter" /* ENTER */ && is.und(payload.from)) {
19117
+ const p2 = propsFn ? propsFn() : props;
19118
+ const from = is.und(p2.initial) || prevTransitions ? p2.from : p2.initial;
19119
+ payload.from = callProp(from, t.item, i);
19120
+ }
19121
+ const { onResolve } = payload;
19122
+ payload.onResolve = (result) => {
19123
+ callProp(onResolve, result);
19124
+ const transitions2 = usedTransitions.current;
19125
+ const t2 = transitions2.find((t3) => t3.key === key);
19126
+ if (!t2)
19127
+ return;
19128
+ if (result.cancelled && t2.phase != "update" /* UPDATE */) {
19129
+ return;
19130
+ }
19131
+ if (t2.ctrl.idle) {
19132
+ const idle = transitions2.every((t3) => t3.ctrl.idle);
19133
+ if (t2.phase == "leave" /* LEAVE */) {
19134
+ const expiry = callProp(expires, t2.item);
19135
+ if (expiry !== false) {
19136
+ const expiryMs = expiry === true ? 0 : expiry;
19137
+ t2.expired = true;
19138
+ if (!idle && expiryMs > 0) {
19139
+ if (expiryMs <= 2147483647)
19140
+ t2.expirationId = setTimeout(forceUpdate, expiryMs);
19141
+ return;
19142
+ }
19143
+ }
19144
+ }
19145
+ if (idle && transitions2.some((t3) => t3.expired)) {
19146
+ exitingTransitions.current.delete(t2);
19147
+ if (exitBeforeEnter) {
19148
+ forceChange.current = true;
19149
+ }
19150
+ forceUpdate();
19151
+ }
19152
+ }
19153
+ };
19154
+ const springs = getSprings(t.ctrl, payload);
19155
+ if (phase === "leave" /* LEAVE */ && exitBeforeEnter) {
19156
+ exitingTransitions.current.set(t, { phase, springs, payload });
19157
+ } else {
19158
+ changes.set(t, { phase, springs, payload });
19159
+ }
19160
+ });
19161
+ const context = React.useContext(SpringContext);
19162
+ const prevContext = usePrev(context);
19163
+ const hasContext = context !== prevContext && hasProps(context);
19164
+ useIsomorphicLayoutEffect(() => {
19165
+ if (hasContext) {
19166
+ each(transitions, (t) => {
19167
+ t.ctrl.start({ default: context });
19168
+ });
19169
+ }
19170
+ }, [context]);
19171
+ each(changes, (_, t) => {
19172
+ if (exitingTransitions.current.size) {
19173
+ const ind = transitions.findIndex((state) => state.key === t.key);
19174
+ transitions.splice(ind, 1);
19175
+ }
19176
+ });
19177
+ useIsomorphicLayoutEffect(
19178
+ () => {
19179
+ each(
19180
+ exitingTransitions.current.size ? exitingTransitions.current : changes,
19181
+ ({ phase, payload }, t) => {
19182
+ const { ctrl } = t;
19183
+ t.phase = phase;
19184
+ ref?.add(ctrl);
19185
+ if (hasContext && phase == "enter" /* ENTER */) {
19186
+ ctrl.start({ default: context });
19187
+ }
19188
+ if (payload) {
19189
+ replaceRef(ctrl, payload.ref);
19190
+ if ((ctrl.ref || ref) && !forceChange.current) {
19191
+ ctrl.update(payload);
19192
+ } else {
19193
+ ctrl.start(payload);
19194
+ if (forceChange.current) {
19195
+ forceChange.current = false;
19196
+ }
19197
+ }
19198
+ }
19199
+ }
19200
+ );
19201
+ },
19202
+ reset ? void 0 : deps
19203
+ );
19204
+ const renderTransitions = (render) => /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, transitions.map((t, i) => {
19205
+ const { springs } = changes.get(t) || t.ctrl;
19206
+ const elem = render({ ...springs }, t.item, t, i);
19207
+ return elem && elem.type ? /* @__PURE__ */ React__namespace.createElement(
19208
+ elem.type,
19209
+ {
19210
+ ...elem.props,
19211
+ key: is.str(t.key) || is.num(t.key) ? t.key : t.ctrl.id,
19212
+ ref: elem.ref
19213
+ }
19214
+ ) : elem;
19215
+ }));
19216
+ return ref ? [renderTransitions, ref] : renderTransitions;
19217
+ }
19218
+ var nextKey = 1;
19219
+ function getKeys(items, { key, keys = key }, prevTransitions) {
19220
+ if (keys === null) {
19221
+ const reused = /* @__PURE__ */ new Set();
19222
+ return items.map((item) => {
19223
+ const t = prevTransitions && prevTransitions.find(
19224
+ (t2) => t2.item === item && t2.phase !== "leave" /* LEAVE */ && !reused.has(t2)
19225
+ );
19226
+ if (t) {
19227
+ reused.add(t);
19228
+ return t.key;
19229
+ }
19230
+ return nextKey++;
19231
+ });
19232
+ }
19233
+ return is.und(keys) ? items : is.fun(keys) ? items.map(keys) : toArray(keys);
19234
+ }
18981
19235
  var Interpolation = class extends FrameValue {
18982
19236
  constructor(source, args) {
18983
19237
  super();
@@ -20733,12 +20987,76 @@ const ButtonGroup = (props) => {
20733
20987
  : ''} ${item.buttonProps.extraClassNames}`, onClick: () => onChange && onChange(item?.buttonProps?.value) })) : (React.createElement("div", { key: index, className: ` tw-flex tw-items-center tw-justify-center tw-rounded-none tw-ml-[-1px] active:tw-z-30 ${item?.extraClassNames || ''}` }, item?.element)))));
20734
20988
  };
20735
20989
 
20990
+ /**
20991
+ * Carousel:
20992
+ * - Easily create a carousel with custom slides.
20993
+ * - Supports automatic sliding, navigation arrows, and slide indicators.
20994
+ */
20995
+ const Carousel = ({ testId = 'carousel-id', activeIndex = 0, extraClassNames = '', onSlide = () => { }, autoSlide, showIndicators = true, continuous = true, interval = 4000, prevIcon = 'fc-arrow-dropdown tw-rotate-90', nextIcon = 'fc-arrow-dropdown -tw-rotate-90', showArrows = true, iconExtraClassNames = '', carouselItems = [], }) => {
20996
+ const [currentIndex, setCurrentIndex] = React.useState(activeIndex);
20997
+ const changeSlide = (nextIndex) => {
20998
+ const newIndex = nextIndex % carouselItems.length;
20999
+ setCurrentIndex(newIndex);
21000
+ onSlide(newIndex, newIndex > currentIndex ? 'right' : 'left');
21001
+ };
21002
+ React.useEffect(() => {
21003
+ if (autoSlide) {
21004
+ const currentInterval = setInterval(() => {
21005
+ if (continuous) {
21006
+ setCurrentIndex((prevCurrentIndex) => {
21007
+ onSlide((prevCurrentIndex + 1) % carouselItems.length, (prevCurrentIndex + 1) % carouselItems.length > prevCurrentIndex ? 'right' : 'left');
21008
+ return (prevCurrentIndex + 1) % carouselItems.length;
21009
+ });
21010
+ }
21011
+ else if (currentIndex === carouselItems.length - 1) {
21012
+ clearInterval(currentInterval);
21013
+ }
21014
+ else {
21015
+ changeSlide(currentIndex + 1);
21016
+ }
21017
+ }, interval);
21018
+ return () => clearInterval(currentInterval);
21019
+ }
21020
+ }, [autoSlide]);
21021
+ React.useEffect(() => {
21022
+ if (activeIndex && activeIndex !== currentIndex) {
21023
+ setCurrentIndex(activeIndex);
21024
+ }
21025
+ }, [activeIndex]);
21026
+ const transitions = useTransition([currentIndex], {
21027
+ keys: null,
21028
+ exitBeforeEnter: true,
21029
+ from: { transform: 'translate3d(100%,0,0)' },
21030
+ enter: { transform: 'translate3d(0%,0,0)' },
21031
+ leave: { transform: 'translate3d(0%,0,0)' },
21032
+ });
21033
+ const onBackClick = () => {
21034
+ if (currentIndex === 0 && !continuous) {
21035
+ return;
21036
+ }
21037
+ changeSlide((currentIndex - 1) % carouselItems.length);
21038
+ };
21039
+ const onForwardClick = () => {
21040
+ if (currentIndex === carouselItems.length - 1 && !continuous) {
21041
+ return;
21042
+ }
21043
+ changeSlide((currentIndex + 1) % carouselItems.length);
21044
+ };
21045
+ return (React.createElement("div", { "data-testid": testId, className: `tw-flex tw-flex-col tw-items-center tw-justify-center tw-w-full ${extraClassNames}` },
21046
+ React.createElement("div", { className: "tw-flex tw-items-center tw-w-full tw-h-max tw-gap-1" },
21047
+ showArrows && (React.createElement(Button, { icon: prevIcon, size: "lg", variant: "no-border", testId: "carousel-prev", extraClassNames: `${currentIndex === 0 && !continuous ? 'tw-invisible' : ''} ${iconExtraClassNames} tw-animate-fadeIn`, onClick: onBackClick })),
21048
+ transitions((style, i) => (React.createElement(animated.div, { "data-testid": `${testId}-${currentIndex}`, style: style }, carouselItems[currentIndex]))),
21049
+ showArrows && (React.createElement(Button, { icon: nextIcon, testId: "carousel-next", size: "lg", variant: "no-border", extraClassNames: `${currentIndex === carouselItems.length - 1 && !continuous ? 'tw-invisible' : ''} ${iconExtraClassNames} tw-animate-fadeIn`, onClick: onForwardClick }))),
21050
+ showIndicators && (React.createElement("div", { className: "tw-flex tw-gap-1 tw-mt-2" }, carouselItems.map((_, i) => (React.createElement("div", { key: i, className: `tw-w-2 tw-h-2 tw-rounded-full tw-cursor-pointer ${i === currentIndex ? 'tw-bg-sq-color-dark' : 'tw-bg-sq-darkish-gray'}`, onClick: () => changeSlide(i) })))))));
21051
+ };
21052
+
20736
21053
  exports.Accordion = Accordion;
20737
21054
  exports.Alert = Alert;
20738
21055
  exports.Button = Button;
20739
21056
  exports.ButtonGroup = ButtonGroup;
20740
21057
  exports.ButtonWithDropdown = ButtonWithDropdown;
20741
21058
  exports.ButtonWithPopover = ButtonWithPopover;
21059
+ exports.Carousel = Carousel;
20742
21060
  exports.Checkbox = Checkbox;
20743
21061
  exports.Collapse = Collapse;
20744
21062
  exports.Icon = Icon;