@app-studio/web 0.8.63 → 0.8.65

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.
@@ -1,12 +1,44 @@
1
1
  import React from 'react';
2
2
  import { TabsStyles, Tab } from './Tabs.type';
3
+ /**
4
+ * Props for the main Tabs component (External API).
5
+ */
3
6
  export interface TabsProps {
7
+ /** Array of tab objects to be displayed. Each tab needs a unique `value`. */
4
8
  tabs: Tab[];
9
+ /** Optional value of the tab to be active initially. Defaults to the first tab if not provided or not found. */
10
+ initialTabValue?: string | number;
11
+ /** Optional callback function triggered when the active tab changes. Receives the newly active tab object. */
12
+ onTabChange?: (activeTab: Tab) => void;
13
+ /** Optional styles object to customize the appearance of the tabs container, headers, buttons, text, and content area. */
5
14
  styles?: TabsStyles;
15
+ /**
16
+ * Optional custom renderer for a single tab button/header.
17
+ * Receives the tab data, whether it's currently active, and an onClick handler to activate the tab.
18
+ */
19
+ renderTab?: (tab: Tab, isActive: boolean, onClick: () => void) => React.ReactNode;
20
+ /**
21
+ * Optional custom renderer for the content area.
22
+ * Receives the currently active tab object.
23
+ * If not provided, the `content` property from the active tab object will be rendered.
24
+ */
25
+ renderContent?: (activeTab: Tab) => React.ReactNode;
6
26
  }
7
- export interface TabsViewProps extends TabsProps {
8
- isActive: Tab;
9
- setIsActive: React.Dispatch<React.SetStateAction<Tab>>;
10
- tabsState: Tab[];
11
- setTabsState: React.Dispatch<React.SetStateAction<Tab[]>>;
27
+ /**
28
+ * Props specifically for the TabsView component (Internal).
29
+ * These props are derived or passed down from the main Tabs component.
30
+ */
31
+ export interface TabsViewProps {
32
+ /** The original array of tab objects. */
33
+ tabs: Tab[];
34
+ /** The currently active tab object, or undefined if none is active. */
35
+ activeTab: Tab | undefined;
36
+ /** Callback function to handle clicking on a tab header/button. */
37
+ handleTabClick: (tab: Tab) => void;
38
+ /** Optional styles object. */
39
+ styles?: TabsStyles;
40
+ /** Optional custom renderer for a tab button/header. */
41
+ renderTab?: (tab: Tab, isActive: boolean, onClick: () => void) => React.ReactNode;
42
+ /** Optional custom renderer for the content area. */
43
+ renderContent?: (activeTab: Tab) => React.ReactNode;
12
44
  }
@@ -1,8 +1,12 @@
1
1
  /// <reference types="react" />
2
2
  import { Tab } from './Tabs.type';
3
- export declare const useTabsState: (propTabs: Tab[]) => {
4
- isActive: Tab;
5
- setIsActive: import("react").Dispatch<import("react").SetStateAction<Tab>>;
6
- tabsState: Tab[];
7
- setTabsState: import("react").Dispatch<import("react").SetStateAction<Tab[]>>;
3
+ /**
4
+ * Custom hook to manage the state of the active tab.
5
+ * @param propTabs - The array of tab objects provided as props.
6
+ * @param initialTabValue - The optional title of the tab to be initially active.
7
+ * @returns An object containing the current activeTab and a function to update it.
8
+ */
9
+ export declare const useTabsState: (propTabs: Tab[], initialTabValue?: string | number | undefined) => {
10
+ activeTab: Tab | undefined;
11
+ setActiveTab: import("react").Dispatch<import("react").SetStateAction<Tab | undefined>>;
8
12
  };
@@ -1,3 +1,6 @@
1
- import { TabsViewProps } from './Tabs.props';
2
1
  import React from 'react';
3
- export declare const TabsView: (props: TabsViewProps) => React.JSX.Element;
2
+ import { TabsViewProps } from './Tabs.props';
3
+ /**
4
+ * The presentation component for Tabs. Renders the UI based on props.
5
+ */
6
+ export declare const TabsView: React.FC<TabsViewProps>;
@@ -2,7 +2,7 @@ import { CSSProperties } from 'react';
2
2
  import type { TextProps as TextAppProps } from 'app-studio';
3
3
  import { Headings, Size, TextWeights } from './Text.type';
4
4
  export interface TextProps extends Omit<TextAppProps, 'children' | 'style' | 'pointerEvents'>, CSSProperties {
5
- children: React.ReactNode;
5
+ children?: React.ReactNode;
6
6
  heading?: Headings;
7
7
  isItalic?: boolean;
8
8
  isStriked?: boolean;
@@ -7657,89 +7657,147 @@ Table.Caption = TableCaption;
7657
7657
  Table.Container = TableContainer;
7658
7658
  Table.Template = TableView;
7659
7659
 
7660
- // Initializes a custom hook for managing tab states with an array of 'Tab' objects passed as properties.
7661
- var useTabsState = propTabs => {
7662
- var [isActive, setIsActive] = React.useState(propTabs[0]);
7663
- var [tabsState, setTabsState] = React.useState(propTabs);
7660
+ /**
7661
+ * Custom hook to manage the state of the active tab.
7662
+ * @param propTabs - The array of tab objects provided as props.
7663
+ * @param initialTabValue - The optional title of the tab to be initially active.
7664
+ * @returns An object containing the current activeTab and a function to update it.
7665
+ */
7666
+ var useTabsState = (propTabs, initialTabValue) => {
7667
+ // Find the initial tab based on initialTabValue, or default to the first tab.
7668
+ // Ensure propTabs is not empty before accessing index 0.
7669
+ var findInitialTab = () => {
7670
+ if (!propTabs || propTabs.length === 0) {
7671
+ return undefined; // No tabs, no initial active tab
7672
+ }
7673
+ if (initialTabValue !== undefined) {
7674
+ var foundTab = propTabs.find(tab => tab.title === initialTabValue);
7675
+ if (foundTab) {
7676
+ return foundTab;
7677
+ }
7678
+ // Warn if initialTabValue is provided but not found
7679
+ console.warn("Tabs: initialTabValue \"" + initialTabValue + "\" not found in tabs. Defaulting to the first tab.");
7680
+ }
7681
+ return propTabs[0]; // Default to the first tab
7682
+ };
7683
+ var [activeTab, setActiveTab] = React.useState(findInitialTab);
7684
+ // Effect to update the active tab if the initialTabValue prop changes
7685
+ // or if the tabs array changes and the current active tab is no longer valid.
7686
+ React.useEffect(() => {
7687
+ var newInitialTab = findInitialTab();
7688
+ // Update only if the calculated initial tab is different from the current active tab
7689
+ // or if the current active tab is no longer in the list (and there are tabs)
7690
+ var currentActiveTabStillValid = activeTab && propTabs.some(t => t.title === activeTab.title);
7691
+ if (newInitialTab && (!currentActiveTabStillValid || initialTabValue !== undefined && (activeTab == null ? void 0 : activeTab.title) !== initialTabValue)) {
7692
+ setActiveTab(newInitialTab);
7693
+ } else if (!newInitialTab && activeTab) {
7694
+ // Handle case where all tabs are removed
7695
+ setActiveTab(undefined);
7696
+ }
7697
+ }, [propTabs, initialTabValue]); // Rerun when tabs or initial title changes
7664
7698
  return {
7665
- isActive,
7666
- setIsActive,
7667
- tabsState,
7668
- setTabsState
7699
+ activeTab,
7700
+ setActiveTab
7669
7701
  };
7670
7702
  };
7671
7703
 
7672
- // Defines a functional component 'TabsView' with props of type 'TabsViewProps'.
7673
- var TabsView = props => {
7674
- // Destructures 'tabs', 'styles', 'isActive', 'setIsActive', 'tabsState', and 'setTabsState' from the component props.
7675
- var {
7676
- tabs,
7677
- styles,
7678
- isActive,
7679
- setIsActive,
7680
- tabsState,
7681
- setTabsState
7682
- } = props;
7683
- // Declares a function 'moveSelectedTabToTop' that takes an index and modifies the tabs order.
7684
- var moveSelectedTabToTop = idx => {
7685
- // Creates a copy of the 'tabs' array from props to be altered.
7686
- var newTabs = [...tabs];
7687
- // Removes the tab at the provided index, effectively selecting this tab.
7688
- var selectedTab = newTabs.splice(idx, 1);
7689
- // Places the selected tab at the start of the 'newTabs' array.
7690
- newTabs.unshift(selectedTab[0]);
7691
- // Updates the state with the reordered tabs.
7692
- setTabsState(newTabs);
7693
- // Sets the active tab to the first tab in the 'newTabs' array.
7694
- setIsActive(newTabs[0]);
7695
- };
7696
- // Defines a function 'isContentActive' that checks if the given tab's content is to be displayed.
7697
- var isContentActive = tab => {
7698
- // Returns a boolean indicating if the given tab is identical to the first tab in 'tabsState'.
7699
- return tab.value === tabsState[0].value;
7700
- };
7701
- return /*#__PURE__*/React__default.createElement(Vertical, Object.assign({
7702
- width: "100w",
7703
- height: '100%'
7704
- }, styles == null ? void 0 : styles.container), /*#__PURE__*/React__default.createElement(Horizontal, Object.assign({
7705
- marginBottom: 20
7706
- }, styles == null ? void 0 : styles.headerTabs), tabs.map((tab, idx) => (/*#__PURE__*/React__default.createElement(Button, Object.assign({
7707
- key: tab.title,
7708
- onClick: () => {
7709
- moveSelectedTabToTop(idx);
7710
- },
7711
- variant: isActive.value === tab.value ? 'filled' : 'ghost',
7712
- shape: "pillShaped",
7713
- cursor: "pointer",
7714
- isAuto: true
7715
- }, styles == null ? void 0 : styles.tab, isActive.value === tab.value ? styles == null ? void 0 : styles.activeTab : {}), /*#__PURE__*/React__default.createElement(Text, Object.assign({}, styles == null ? void 0 : styles.title, isActive.value === tab.value ? styles == null ? void 0 : styles.activeText : {}), tab.title))))), /*#__PURE__*/React__default.createElement(View, Object.assign({
7716
- width: '100%',
7717
- height: "100%"
7718
- }, styles == null ? void 0 : styles.content), tabsState.map((tab, idx) => isContentActive(tab) && /*#__PURE__*/React__default.createElement(View, {
7719
- key: idx
7720
- }, tab.content))));
7704
+ /**
7705
+ * The presentation component for Tabs. Renders the UI based on props.
7706
+ */
7707
+ var TabsView = _ref => {
7708
+ var {
7709
+ tabs = [],
7710
+ // Default to empty array
7711
+ activeTab,
7712
+ handleTabClick,
7713
+ styles = {},
7714
+ // Default to empty object
7715
+ renderTab,
7716
+ renderContent
7717
+ } = _ref;
7718
+ // If there's no active tab (e.g., tabs array is empty), render nothing or a placeholder
7719
+ if (!activeTab) {
7720
+ // Optionally render a placeholder when no tabs are active/available
7721
+ // return <View {...styles.container}><Text>No tabs available.</Text></View>;
7722
+ return null; // Or simply render nothing
7723
+ }
7724
+ return (
7725
+ /*#__PURE__*/
7726
+ // Use Vertical layout for overall structure (tabs header above content)
7727
+ React__default.createElement(Vertical, Object.assign({
7728
+ width: "100%",
7729
+ height: '100%'
7730
+ }, styles.container), /*#__PURE__*/React__default.createElement(Horizontal, Object.assign({}, styles.headerTabs), tabs.map(tab => {
7731
+ // Determine if the current tab in the loop is the active one
7732
+ var isActive = tab.title === activeTab.title;
7733
+ // Prepare the onClick handler for this specific tab
7734
+ var onClick = () => handleTabClick(tab);
7735
+ // Use the custom renderTab function if provided
7736
+ if (renderTab) {
7737
+ return renderTab(tab, isActive, onClick);
7738
+ }
7739
+ // Default rendering for a tab button
7740
+ return /*#__PURE__*/React__default.createElement(Button, Object.assign({
7741
+ key: tab.title,
7742
+ onClick: onClick,
7743
+ borderBottomLeftRadius: 0,
7744
+ borderBottomRightRadius: 0
7745
+ }, styles.tab, isActive ? styles.activeTab : {}, {
7746
+ // Example: Set variant based on active state (can be overridden by styles)
7747
+ variant: isActive ? 'filled' : 'ghost',
7748
+ cursor: "pointer" // Ensure pointer cursor
7749
+ }), tab.icon, /*#__PURE__*/React__default.createElement(Text
7750
+ // Apply base title styles and merge activeText styles if this tab is active
7751
+ , Object.assign({}, styles.title, isActive ? styles.activeText : {}), tab.title));
7752
+ })), /*#__PURE__*/React__default.createElement(View, Object.assign({
7753
+ width: '100%',
7754
+ height: "100%"
7755
+ }, styles.content), renderContent ? renderContent(activeTab) :
7756
+ // Otherwise, render the content property from the active tab object
7757
+ activeTab.content))
7758
+ );
7721
7759
  };
7722
7760
 
7761
+ /**
7762
+ * Tabs component allows users to navigate between different sections of content.
7763
+ * It manages the active tab state and renders the corresponding content.
7764
+ */
7723
7765
  var TabsComponent = _ref => {
7724
7766
  var {
7725
7767
  tabs,
7726
- styles
7768
+ styles,
7769
+ initialTabValue,
7770
+ onTabChange,
7771
+ renderTab,
7772
+ renderContent
7727
7773
  } = _ref;
7728
- var {
7729
- isActive,
7730
- setIsActive,
7731
- tabsState,
7732
- setTabsState
7733
- } = useTabsState(tabs);
7774
+ // Use the custom hook to manage the active tab state
7775
+ var {
7776
+ activeTab,
7777
+ setActiveTab
7778
+ } = useTabsState(tabs, initialTabValue);
7779
+ // Handler function to change the active tab and trigger the callback
7780
+ var handleTabClick = tab => {
7781
+ // Only update state and call callback if the clicked tab is different from the current one
7782
+ if ((activeTab == null ? void 0 : activeTab.title) !== tab.title) {
7783
+ setActiveTab(tab);
7784
+ // Call the onTabChange callback if provided
7785
+ if (onTabChange) {
7786
+ onTabChange(tab);
7787
+ }
7788
+ }
7789
+ };
7790
+ // Render the presentation component with the necessary props
7734
7791
  return /*#__PURE__*/React__default.createElement(TabsView, {
7735
7792
  tabs: tabs,
7736
7793
  styles: styles,
7737
- isActive: isActive,
7738
- tabsState: tabsState,
7739
- setTabsState: setTabsState,
7740
- setIsActive: setIsActive
7794
+ activeTab: activeTab,
7795
+ handleTabClick: handleTabClick,
7796
+ renderTab: renderTab,
7797
+ renderContent: renderContent
7741
7798
  });
7742
7799
  };
7800
+ // Export the component wrapped in React.memo for performance optimization
7743
7801
  var Tabs = /*#__PURE__*/React__default.memo(TabsComponent);
7744
7802
 
7745
7803
  // Declares the useToggleState function which takes defaultToggled parameter to initialize the toggle state.