Major refactor, pulled in all types, deleted some components
Some checks failed
armco-org/shared-components/pipeline/head There was a failure building this commit

This commit is contained in:
2025-11-06 02:20:17 +05:30
parent e8ac23b0df
commit c0ecd14e6d
180 changed files with 3954 additions and 22511 deletions

2
Jenkinsfile vendored
View File

@@ -1,6 +1,6 @@
@Library('jenkins-shared') _
kanikoPipeline(
repoName: 'layout',
repoName: 'shared-components',
branch: env.BRANCH_NAME ?: 'main',
isNpmLib: true
)

View File

@@ -1,6 +0,0 @@
{
"name": "@armco/components/TreeViz",
"main": "../build/cjs/TreeViz.js",
"module": "../build/es/TreeViz.js",
"types": "../build/types/TreeViz.d.ts"
}

20903
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -20,33 +20,39 @@
},
"dependencies": {
"@armco/configs": "^0.0.11",
"@armco/utils": "^0.0.29",
"@armco/icon": "^0.0.10",
"@armco/utils": "^0.0.29",
"@tanstack/react-table": "^8.21.2",
"bootstrap": "^5.3.0",
"react-app-polyfill": "^3.0.0",
"react-dev-utils": "^12.0.1",
"react": ">=16.8.0",
"react-app-polyfill": "^3.0.0",
"react-bootstrap": "^2.7.4",
"react-dev-utils": "^12.0.1",
"react-dnd": ">=16.0.0",
"react-dnd-html5-backend": ">=16.0.0",
"react-dnd-touch-backend": ">=16.0.0",
"react-dom": "^18.2.0",
"react-draggable": "^4.4.6",
"resize-observer-polyfill": "^1.5.1",
"react-resizable": "^3.0.5",
"react-router-dom": "^6.13.0",
"resize-observer-polyfill": "^1.5.1",
"uuid": "^9.0.0"
},
"devDependencies": {
"@armco/types": "^0.0.18"
"@armco/types": "^0.0.18",
"@types/react-dom": "^19.2.2",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^5.1.0",
"glob": "^11.0.3",
"sass-embedded": "^1.93.3",
"vite-plugin-dts": "^4.5.4",
"vite-plugin-lib-inject-css": "^2.2.2",
"vite-plugin-svgr": "^4.5.0",
"vitest": "^4.0.7"
},
"peerDependencies": {
"d3": "^7.9.0",
"highcharts": "^12.1.2",
"highcharts-react-official": "^3.2.1",
"highlight.js": "^11.8.0",
"moment": "^2.29.4",
"moment": "^2.29.4"
},
"eslintConfig": {
"extends": [

View File

@@ -1,7 +1,7 @@
import { {{pascalCase name}}Props } from "@armco/types"
import { {{pascalCase name}}Props } from "./types"
import "./{{pascalCase name}}.component.scss"
const {{pascalCase name}} = (props: {{pascalCase name}}Props): JSX.Element => {
const {{pascalCase name}} = (props: {{pascalCase name}}Props): ReactNode => {
return <div className="ar-{{pascalCase name}}">In Component {{pascalCase name}}</div>
}

View File

@@ -2,7 +2,7 @@ import "./{{pascalCase name}}.page.scss"
interface {{pascalCase name}}Props {}
const {{pascalCase name}} = (props: {{pascalCase name}}Props): JSX.Element => {
const {{pascalCase name}} = (props: {{pascalCase name}}Props): ReactNode => {
return <div className="ar-{{pascalCase name}}">In Page {{pascalCase name}}</div>
}

View File

@@ -1,3 +0,0 @@
.ar-AboutUs {
}

View File

@@ -1,7 +1,9 @@
import { AboutUsProps } from "@armco/types"
import "./AboutUs.component.scss"
import { ReactNode } from "react"
import { BaseProps } from "./types"
const AboutUs = (props: AboutUsProps): JSX.Element => {
export interface AboutUsProps extends BaseProps { }
const AboutUs = (props: AboutUsProps): ReactNode => {
return <div className="ar-AboutUs">In Component AboutUs</div>
}

View File

@@ -1,13 +1,30 @@
import { ReactNode, useEffect, useRef, useState } from "react"
import {
ArAccordionVariants,
ArThemes,
AccordionExpansionPanelProps,
AccordionProps,
} from "@armco/types"
import { FunctionType } from "@armco/types"
import { ArAccordionStyles, ArAccordionVariants, ArThemes } from "./enums"
import { BaseProps } from "./types"
import Icon from "@armco/icon"
import "./Accordion.component.scss"
export interface AccordionProps extends BaseProps {
data: Array<AccordionExpansionPanelProps>
firstExpanded?: boolean
variant?: ArAccordionVariants
appearance?: ArAccordionStyles
isRemovable?: boolean
}
export interface AccordionExpansionPanelProps extends BaseProps {
id: string
title: string
expanded?: boolean
isRemovable?: boolean
setExpandedId?: FunctionType
shouldGrow?: boolean
content: ReactNode
}
const AccordionExpansionPanel = (
props: AccordionExpansionPanelProps,
): ReactNode => {
@@ -41,9 +58,8 @@ const AccordionExpansionPanel = (
return (
<div
className={`ar-AccordionExpansionPanel${
shouldGrow ? " show-grow d-flex flex-column flex-grow-1" : ""
}${classes ? " " + classes : ""}${expanded ? " expanded" : ""}`}
className={`ar-AccordionExpansionPanel${shouldGrow ? " show-grow d-flex flex-column flex-grow-1" : ""
}${classes ? " " + classes : ""}${expanded ? " expanded" : ""}`}
id={id}
key={id}
>
@@ -78,9 +94,8 @@ const AccordionExpansionPanel = (
)}
</div>
<div
className={`ar-AccordionExpansionPanel__content${
shouldGrow ? " d-flex flex-grow-1" : ""
}`}
className={`ar-AccordionExpansionPanel__content${shouldGrow ? " d-flex flex-grow-1" : ""
}`}
ref={contentRef}
>
{typeof content === "string" ? (
@@ -93,7 +108,7 @@ const AccordionExpansionPanel = (
)
}
const Accordion = (props: AccordionProps): JSX.Element => {
const Accordion = (props: AccordionProps): ReactNode => {
const {
appearance,
classes,
@@ -127,9 +142,8 @@ const Accordion = (props: AccordionProps): JSX.Element => {
return (
<div
className={`ar-Accordion${classes ? " " + classes : ""}${
appearance ? " " + appearance : ""
}`}
className={`ar-Accordion${classes ? " " + classes : ""}${appearance ? " " + appearance : ""
}`}
>
{localData?.map((item, index) => {
item.setExpandedId = setExpanded

View File

@@ -1,11 +1,18 @@
import { useEffect, useState } from "react"
import { AdvancedColorPickerProps } from "@armco/types"
import { ReactNode, useEffect, useState } from "react"
import { hslToHex, hexToHsl } from "@armco/utils/domHelper"
import { BaseProps } from "./types"
import Slider from "./Slider"
import COLOR_PICKER_CONFIG from "./ColorPickerConfig"
import "./AdvancedColorPicker.component.scss"
const AdvancedColorPicker = (props: AdvancedColorPickerProps): JSX.Element => {
export interface AdvancedColorPickerProps extends BaseProps {
displaySample?: boolean;
id?: string;
onColorSelect?: (arg: string) => void;
title?: string;
}
const AdvancedColorPicker = (props: AdvancedColorPickerProps): ReactNode => {
const { demo, displaySample, id, onColorSelect, title } = props
const [color, setColor] = useState<string>()
const [hue, setHue] = useState<number>()
@@ -89,7 +96,7 @@ const AdvancedColorPicker = (props: AdvancedColorPickerProps): JSX.Element => {
label="Hue"
min={0}
max={255}
onChange={(e) =>
onChange={(e: any) =>
setHue(parseInt((e.target as HTMLInputElement).value) / 255)
}
withManual
@@ -98,7 +105,7 @@ const AdvancedColorPicker = (props: AdvancedColorPickerProps): JSX.Element => {
label="Saturation"
min={0}
max={100}
onChange={(e) =>
onChange={(e: any) =>
setSaturation(parseInt((e.target as HTMLInputElement).value) / 100)
}
withManual
@@ -107,7 +114,7 @@ const AdvancedColorPicker = (props: AdvancedColorPickerProps): JSX.Element => {
label="Lightness"
min={0}
max={100}
onChange={(e) =>
onChange={(e: any) =>
setLightness(parseInt((e.target as HTMLInputElement).value) / 100)
}
withManual

View File

@@ -1,10 +1,21 @@
import { useEffect, useState } from "react"
import { AlertProps, ArThemes } from "@armco/types"
import { ReactNode, useEffect, useState } from "react"
import { ArAlertType, ArThemes } from "./enums"
import { BaseProps } from "./types"
import Icon from "@armco/icon"
import "./Alert.component.scss"
export interface AlertProps extends BaseProps {
closeable?: boolean
position?: string
show?: boolean
type?: ArAlertType
message: string | ReactNode
timeout?: number
uid: string
}
let timeoutRef: any
const Alert = (props: AlertProps): JSX.Element => {
const Alert = (props: AlertProps): ReactNode => {
const {
classes,
closeable,
@@ -50,9 +61,8 @@ const Alert = (props: AlertProps): JSX.Element => {
return (
<div
className={`ar-Alert position-fixed d-flex ${position || "top-center"}${
classes ? " " + classes : ""
} ${type || "information"}${showClass ? " " + showClass : ""}`}
className={`ar-Alert position-fixed d-flex ${position || "top-center"}${classes ? " " + classes : ""
} ${type || "information"}${showClass ? " " + showClass : ""}`}
>
<span className="ar-Alert__icon d-inline-block p-2">
<Icon

View File

@@ -1,10 +1,11 @@
import { ReactNode } from "react"
import "./AlertStackManager.component.scss"
interface AlertStackManagerProps {
export interface AlertStackManagerProps {
max?: number
}
const AlertStackManager = (props: AlertStackManagerProps): JSX.Element => {
const AlertStackManager = (props: AlertStackManagerProps): ReactNode => {
return (
<div className="ar-AlertStackManager">In Component AlertStackManager</div>
)

View File

@@ -1,12 +1,14 @@
import { ArPillSizes, BasicFilterConfig } from "@armco/types"
import { ReactNode } from "react"
import { BasicFilterConfig } from "@armco/types"
import { ArPillSizes } from "./enums"
import SelectionPill from "./SelectionPill"
import "./AlphabetFilter.component.scss"
interface AlphabetFilterProps {
export interface AlphabetFilterProps {
onSelectionChanged: Function
}
const AlphabetFilter = (props: AlphabetFilterProps): JSX.Element => {
const AlphabetFilter = (props: AlphabetFilterProps): ReactNode => {
const { onSelectionChanged } = props
const alpha = Array.from(Array(26)).map((e, i) => i + 65)
const alphabet = alpha.map((x) => String.fromCharCode(x))

View File

@@ -1,7 +1,15 @@
import { AnchorProps } from "@armco/types"
import { ReactNode } from "react"
import { FunctionType } from "@armco/types"
import { BaseProps } from "./types"
import "./Anchor.component.scss"
const Anchor = (props: AnchorProps): JSX.Element => {
export interface AnchorProps extends BaseProps {
text: string
href?: string
onClick?: FunctionType
}
const Anchor = (props: AnchorProps): ReactNode => {
const { classes, text, ...rest } = props
return (
<a className={`ar-Anchor${classes ? " " + classes : ""}`} {...rest}>

View File

@@ -1,16 +1,29 @@
import { ReactNode } from "react"
import { useNavigate } from "react-router-dom"
import { AppNavigatorDataType, FunctionType } from "@armco/types"
import { BaseProps } from "./types"
import {
ArThemes,
ArButtonVariants,
ArSizes,
AppAndToolsSelectorProps,
AppTileProps,
} from "@armco/types"
} from "./enums"
import Icon from "@armco/icon"
import { useTheme } from "@armco/utils/hooks"
import Button from "./Button"
import "./AppAndToolsSelector.component.scss"
export interface AppAndToolsSelectorProps extends BaseProps {
data: Array<AppNavigatorDataType>
}
export interface AppTileProps extends BaseProps {
label: string
icon: string
url?: string
onClick?: FunctionType
description?: Array<string>
}
const AppTile = (props: AppTileProps) => {
const { classes, label, icon, url, theme } = props
const navigate = useNavigate()
@@ -39,7 +52,7 @@ const AppTile = (props: AppTileProps) => {
)
}
const AppAndToolsSelector = (props: AppAndToolsSelectorProps): JSX.Element => {
const AppAndToolsSelector = (props: AppAndToolsSelectorProps): ReactNode => {
const { data } = props
const { theme } = useTheme()
return (

View File

@@ -1,9 +1,9 @@
import React from "react"
import { ReactNode } from "react"
import "./Application.component.scss"
interface ApplicationProps {}
export interface ApplicationProps { }
const Application = (props: any): JSX.Element => {
const Application = (props: ApplicationProps): ReactNode => {
return (
<div className="ar-Application">
In Component Application

View File

@@ -1,18 +1,17 @@
import { ChangeEvent, useEffect, useState } from "react"
import { ChangeEvent, ReactNode, useEffect, useState } from "react"
import {
ArDndItemTypes,
ArIconTileTypes,
ArIconsViewerProps,
ArPopoverSlots,
ArThemes,
SegmentData,
IconResponse,
ArIconSourceTypes,
} from "@armco/types"
} from "./enums"
import { SegmentData, IconResponse } from "@armco/types"
import { ENDPOINTS, STATIC_HOST } from "@armco/configs/endpoints"
import { useTheme } from "@armco/utils/hooks"
import { debounce } from "@armco/utils/helper"
import Icon from "@armco/icon"
import { BaseProps } from "./types"
import ScrollPagination from "./ScrollPagination"
import SearchField from "./SearchField"
import SegmentedControl from "./SegmentedControl"
@@ -43,7 +42,14 @@ const compactionStyles = [
},
]
const ArIconsViewer = (props: ArIconsViewerProps): JSX.Element => {
export interface ArIconsViewerProps extends BaseProps {
view?: SegmentData;
hasSearch?: boolean;
hasViewSelector?: boolean;
isDraggable?: boolean;
}
const ArIconsViewer = (props: ArIconsViewerProps): ReactNode => {
const {
demo,
view: externalView,
@@ -66,11 +72,10 @@ const ArIconsViewer = (props: ArIconsViewerProps): JSX.Element => {
const getItem = (icon: IconResponse) => (
<span
className={`ar-ArIconsViewer__icon-container border-radius-l1 h-100 w-100${
view.name !== ArIconTileTypes.LIST
? " flex-center"
: " border flex-v-center"
}`}
className={`ar-ArIconsViewer__icon-container border-radius-l1 h-100 w-100${view.name !== ArIconTileTypes.LIST
? " flex-center"
: " border flex-v-center"
}`}
slot={ArPopoverSlots.ANCHOR}
>
<Icon

View File

@@ -1,3 +0,0 @@
.ar-ArViz {
}

View File

@@ -1,45 +0,0 @@
import { useEffect, useRef } from "react"
import { select } from "d3"
import { ArVisualizationTypes, ArVizProps, ObjectType } from "@armco/types"
import { generateBubbleChart } from "@armco/utils/chartGenerators"
import BubbleChart from "./BubbleChart"
import "./ArViz.component.scss"
// TODO: Replace this with ArViz dummy in dummies.txt
const dataDummy = {}
const ArViz = (props: ArVizProps): JSX.Element => {
const { clickHandler, type, data } = props
const svgContainerRef = useRef(null)
useEffect(() => {
if (data && svgContainerRef.current) {
switch (type) {
case ArVisualizationTypes.BUBBLE:
generateBubbleChart(dataDummy)
}
const svg = svgContainerRef.current as SVGSVGElement
const boundingBox = svg.getBBox()
const svgToUpdate = select("#ar-ArViz__chart-container")
svgToUpdate.attr(
"viewBox",
`${boundingBox.x} ${boundingBox.y} ${boundingBox.width} ${boundingBox.height}`,
)
}
}, [svgContainerRef, data, type])
return type === ArVisualizationTypes.BUBBLE ? (
<BubbleChart data={data as Array<ObjectType>} clickHandler={clickHandler} />
) : (
<div className="ar-ArViz h-100 w-100 overflow-auto p-3">
<svg
id="ar-ArViz__chart-container"
className="h-100 w-100"
ref={svgContainerRef}
viewBox=""
/>
</div>
)
}
export default ArViz

View File

@@ -1,9 +1,15 @@
import { ArmcoIamProviderProps, ArDefaultLoginPage } from "@armco/types"
import { ReactNode } from "react"
import { WEB_CONFIG } from "@armco/configs/endpoints"
import { BaseProps } from "./types"
import { ArDefaultLoginPage } from "./enums"
import LoginProvider from "./LoginProvider"
import "./ArmcoIamProvider.component.scss"
const ArmcoIamProvider = (props: ArmcoIamProviderProps): JSX.Element => {
export interface ArmcoIamProviderProps extends BaseProps {
defaultPage?: ArDefaultLoginPage
}
const ArmcoIamProvider = (props: ArmcoIamProviderProps): ReactNode => {
const { defaultPage } = props
return (
<LoginProvider

View File

@@ -1,8 +1,18 @@
import { BadgeProps } from "@armco/types"
import { ReactNode } from "react"
import { BaseProps } from "./types";
import { ArBadgeType, ArSizes } from "./enums";
import Icon from "@armco/icon"
import "./Badge.component.scss"
const Badge = (props: BadgeProps): JSX.Element => {
export interface BadgeProps extends BaseProps {
icon?: string;
size?: ArSizes;
shadow?: boolean;
text?: string;
type?: ArBadgeType;
}
const Badge = (props: BadgeProps): ReactNode => {
const { classes, icon, size, shadow, style, text, type } = props
if (icon?.indexOf("/") === -1) {
console.warn(
@@ -11,9 +21,8 @@ const Badge = (props: BadgeProps): JSX.Element => {
}
return (
<span
className={`ar-Badge${size ? " " + size : " regular"}${
type ? " " + type : " inprogress"
}${shadow ? " shadow" : ""}${classes ? " " + classes : ""}`}
className={`ar-Badge${size ? " " + size : " regular"}${type ? " " + type : " inprogress"
}${shadow ? " shadow" : ""}${classes ? " " + classes : ""}`}
style={style}
>
{icon && size !== "small" && <Icon icon={icon} />}

View File

@@ -1,9 +1,9 @@
import React from "react"
import { ReactNode } from "react"
import "./Banner.component.scss"
interface BannerProps {}
export interface BannerProps { }
const Banner = (props: any): JSX.Element => {
const Banner = (props: BannerProps): ReactNode => {
return (
<div className="ar-Banner">
In Component Banner

View File

@@ -1,9 +1,9 @@
import React from "react"
import React, { ReactNode } from "react"
import "./Benefits.component.scss"
interface BenefitsProps {}
export interface BenefitsProps { }
const Benefits = (props: any): JSX.Element => {
const Benefits = (props: BenefitsProps): ReactNode => {
return (
<div className="ar-Benefits">
In Component Benefits

View File

@@ -1,9 +1,9 @@
import React from "react"
import { ReactNode } from "react"
import "./Blog.component.scss"
interface BlogProps {}
export interface BlogProps { }
const Blog = (props: any): JSX.Element => {
const Blog = (props: BlogProps): ReactNode => {
return (
<div className="ar-Blog">
In Component Blog

View File

@@ -1,9 +1,9 @@
import React from "react"
import { ReactNode } from "react"
import "./Brands.component.scss"
interface BrandsProps {}
export interface BrandsProps { }
const Brands = (props: any): JSX.Element => {
const Brands = (props: BrandsProps): ReactNode => {
return (
<div className="ar-Brands">
In Component Brands

View File

@@ -1,14 +1,19 @@
import { ReactNode } from "react"
import { useNavigate } from "react-router-dom"
import {
ArButtonVariants,
ArSizes,
BreadCrumbData,
BreadcrumbProps,
} from "@armco/types"
import { BreadCrumbData } from "@armco/types"
import { BaseProps } from "./types"
import { ArButtonVariants, ArSizes } from "./enums"
import Button from "./Button"
import "./Breadcrumb.component.scss"
const Breadcrumb = (props: BreadcrumbProps): JSX.Element => {
export interface BreadcrumbProps extends BaseProps {
data: Array<BreadCrumbData>
separator?: string
size?: ArSizes
onClick?: Function
}
const Breadcrumb = (props: BreadcrumbProps): ReactNode => {
const { classes, data, demo, separator, size, onClick } = props
const navigate = useNavigate()
@@ -41,8 +46,8 @@ const Breadcrumb = (props: BreadcrumbProps): JSX.Element => {
"onClick" in node
? (e) => node.onClick(e, node.data)
: onClick
? (e) => onClick(e, node.data)
: () => navigate("route" in node ? node.route : "")
? (e) => onClick(e, node.data)
: () => navigate("route" in node ? node.route : "")
}
/>
{index < nodes.length - 1 && (separator || "/")}

View File

@@ -1,3 +0,0 @@
.ar-Breadcrumbs {
}

View File

@@ -1,14 +0,0 @@
import React from "react"
import "./Breadcrumbs.component.scss"
interface BreadcrumbsProps {}
const Breadcrumbs = (props: any): JSX.Element => {
return (
<div className="ar-Breadcrumbs">
In Component Breadcrumbs
</div>
)
}
export default Breadcrumbs

View File

@@ -1,5 +1,7 @@
import { ReactNode } from "react"
import { v4 as uuid } from "uuid"
import { ArThemes, BrowserIncompatibilityProps } from "@armco/types"
import type { BaseProps } from "./types"
import { ArThemes } from "./enums"
import { copyToClipboard } from "@armco/utils/helper"
import { useTheme } from "@armco/utils/hooks"
import Icon from "@armco/icon"
@@ -7,9 +9,15 @@ import Alert from "./Alert"
import Link from "./Link"
import "./BrowserIncompatibility.component.scss"
export interface BrowserIncompatibilityProps extends BaseProps {
applicationName?: string
moreLink?: string
}
const BrowserIncompatibility = (
props: BrowserIncompatibilityProps,
): JSX.Element => {
): ReactNode => {
const { applicationName, moreLink } = props
const { theme } = useTheme()
const demoDummyLink = "https://notabuck.com/armco-design-system/docs/devices"

View File

@@ -1,3 +0,0 @@
.ar-BubbleChart {
}

View File

@@ -1,107 +0,0 @@
import { useEffect, useRef } from "react"
import Highcharts from "highcharts"
import "highcharts/highcharts-more"
import { BubbleChartProps, ObjectType } from "@armco/types"
import "./BubbleChart.component.scss"
const BubbleChart = (props: BubbleChartProps): JSX.Element => {
const { clickHandler, data } = props
const chartRef = useRef(null)
useEffect(() => {
if (!Highcharts) {
if (chartRef.current) {
;(chartRef.current as HTMLDivElement).innerHTML = `
<div style="color: #ff4d4f; font-family: monospace; padding: 10px; border: 1px solid #ff4d4f; border-radius: 4px;">
Highcharts is not installed. Please install highcharts to use BubbleChart.
</div>
`
}
return
}
if (chartRef.current && data) {
const labels = Object.keys(data)
const values = Object.values(data)
const options = {
chart: {
type: "packedbubble",
},
title: {
text: null,
},
tooltip: {
formatter: function (): string {
return (
"Tag: <b>" +
("point" in this && (this.point as ObjectType).name) +
"</b><br>Count: <b>" +
("y" in this && this.y) +
"</b>"
)
},
},
credits: {
enabled: false,
},
plotOptions: {
packedbubble: {
minSize: "30%",
maxSize: "120%",
zMin: 0,
zMax: 1000,
layoutAlgorithm: {
splitSeries: false,
gravitationalConstant: 0.02,
},
dataLabels: {
enabled: true,
format: "{point.name}",
filter: {
property: "y",
operator: ">",
value: 250,
},
style: {
color: "black",
textOutline: "none",
fontWeight: "normal",
},
},
events: {
click: function (e: any) {
clickHandler && clickHandler(e)
},
},
},
},
series: [
{
cursor: "pointer",
showInLegend: false,
data: labels.map((label, index) => ({
// x: index, // X-axis position
// y: values[index], // Y-axis value
// z: values[index], // Bubble size value
value: values[index],
name: label, // Label for the bubble
})),
},
],
xAxis: {
visible: false,
},
yAxis: {
visible: false,
},
}
// @ts-ignore
Highcharts.chart(chartRef.current, options)
}
}, [data]) // Re-render chart when data prop changes
return <div ref={chartRef} style={{ width: "100%" }}></div>
}
export default BubbleChart

View File

@@ -1,3 +0,0 @@
.ar-BubbleViz {
}

View File

@@ -1,10 +0,0 @@
import { BubbleVizProps } from "@armco/types"
import "./BubbleViz.component.scss"
const BubbleViz = (props: BubbleVizProps): JSX.Element => {
const { classes } = props
return <div className={`ar-BubbleViz${classes ? " " + classes : ""}`}></div>
}
export default BubbleViz

View File

@@ -1,14 +1,32 @@
import { useState } from "react"
import { CSSProperties, MouseEventHandler, ReactNode, useState } from "react"
import { FunctionType } from "@armco/types"
import {
ArButtonTypes,
ArButtonVariants,
ArSizes,
ArThemes,
ButtonProps,
} from "@armco/types"
} from "./enums"
import { BaseProps } from "./types"
import Icon from "@armco/icon"
import "./Button.component.scss"
export interface ButtonProps extends BaseProps {
content?: ReactNode | FunctionType
color?: string
contentClasses?: string
contentStyles?: CSSProperties
disabled?: boolean
preIcon?: string
postIcon?: string
onClick?: MouseEventHandler<HTMLButtonElement>
onMouseEnter?: MouseEventHandler<HTMLButtonElement>
onMouseLeave?: MouseEventHandler<HTMLButtonElement>
size?: string
type?: ArButtonTypes
variant?: ArButtonVariants
withSplitOptions?: boolean
}
const Button = (props: ButtonProps) => {
const {
classes,
@@ -51,8 +69,8 @@ const Button = (props: ButtonProps) => {
? "black"
: "white"
: theme === ArThemes.DARK1
? "white"
: "#3232d8"
? "white"
: "#3232d8"
} else {
setColor = "white"
}
@@ -62,11 +80,9 @@ const Button = (props: ButtonProps) => {
return (
<button
type={type}
className={`ar-Button d-inline-flex ar-Button__main fw-bold flex-center${
classes ? " " + classes : ""
}${variant ? " ar-" + variant : ""}${size ? " ar-" + size : ""}${
withSplitOptions ? " has-split-button" : ""
}`}
className={`ar-Button d-inline-flex ar-Button__main fw-bold flex-center${classes ? " " + classes : ""
}${variant ? " ar-" + variant : ""}${size ? " ar-" + size : ""}${withSplitOptions ? " has-split-button" : ""
}`}
onClick={onClick}
style={btnStyles}
onMouseEnter={(e) => {
@@ -95,9 +111,8 @@ const Button = (props: ButtonProps) => {
</span>
{postIcon && (
<span
className={`ar-Button__icon flex-center post${
content ? " ms-2" : ""
}`}
className={`ar-Button__icon flex-center post${content ? " ms-2" : ""
}`}
>
<Icon
icon={postIcon}

View File

@@ -1,13 +1,18 @@
import { CardProps } from "@armco/types"
import { ReactNode } from "react"
import type { BaseProps } from "./types"
import "./Card.component.scss"
const Card = (props: CardProps): JSX.Element => {
export interface CardProps extends BaseProps {
children?: ReactNode
header?: ReactNode
}
const Card = (props: CardProps): ReactNode => {
const { children, classes, header } = props
return (
<div
className={`ar-Card border d-flex flex-column${
classes ? " " + classes : ""
}`}
className={`ar-Card border d-flex flex-column${classes ? " " + classes : ""
}`}
>
{header && (
<div className="w-100 fw-bold p-2 border-bottom">{header}</div>

View File

@@ -1,9 +1,9 @@
import React from "react"
import { ReactNode } from "react"
import "./Careers.component.scss"
interface CareersProps {}
export interface CareersProps { }
const Careers = (props: any): JSX.Element => {
const Careers = (props: CareersProps): ReactNode => {
return (
<div className="ar-Careers">
In Component Careers

View File

@@ -1,3 +0,0 @@
.ar-Carousel {
}

View File

@@ -1,911 +0,0 @@
import { Children, Component, ReactNode } from "react"
import { AnimationHandler, CarouselProps, SwiperProps } from "@armco/types"
import { isKeyboardEvent } from "@armco/utils/domHelper"
import klass from "./cssClasses"
import Thumbs from "./Thumbs"
import {
slideAnimationHandler,
slideSwipeAnimationHandler,
slideStopSwipingHandler,
fadeAnimationHandler,
} from "./animations"
import Swiper from "./Swiper"
import "./Carousel.component.scss"
export interface CarouselState {
autoPlay?: boolean
cancelClick: boolean
hasMount: boolean
initialized: boolean
isMouseEntered: boolean
itemSize: number
previousItem: number
selectedItem: number
swiping?: boolean
swipeMovementStarted: boolean
itemListStyle?: React.CSSProperties
slideStyle?: React.CSSProperties
selectedStyle?: React.CSSProperties
prevStyle?: React.CSSProperties
}
const noop = () => {}
const defaultStatusFormatter = (current: number, total: number) =>
`${current} of ${total}`
export default class Carousel extends Component<CarouselProps, CarouselState> {
private thumbsRef?: Thumbs
private carouselWrapperRef?: HTMLDivElement
// @ts-ignore
private listRef?: HTMLElement | HTMLUListElement
private itemsRef?: HTMLElement[]
private timer?: ReturnType<typeof setTimeout>
private animationHandler: AnimationHandler
static displayName = "Carousel"
static defaultProps: CarouselProps = {
ariaLabel: undefined,
axis: "horizontal",
centerSlidePercentage: 80,
interval: 3000,
labels: {
leftArrow: "previous slide / item",
rightArrow: "next slide / item",
item: "slide item",
},
onClickItem: noop,
onClickThumb: noop,
onChange: noop,
onSwipeStart: () => {},
onSwipeEnd: () => {},
onSwipeMove: () => false,
preventMovementUntilSwipeScrollTolerance: false,
renderArrowPrev: (
onClickHandler: () => void,
hasPrev: boolean,
label: string,
) => (
<button
type="button"
aria-label={label}
className={klass.ARROW_PREV(!hasPrev)}
onClick={onClickHandler}
/>
),
renderArrowNext: (
onClickHandler: () => void,
hasNext: boolean,
label: string,
) => (
<button
type="button"
aria-label={label}
className={klass.ARROW_NEXT(!hasNext)}
onClick={onClickHandler}
/>
),
renderIndicator: (
onClickHandler: (e: React.MouseEvent | React.KeyboardEvent) => void,
isSelected: boolean,
index: number,
label: string,
) => {
return (
<li
className={klass.DOT(isSelected)}
onClick={onClickHandler}
onKeyDown={onClickHandler}
value={index}
key={index}
role="button"
tabIndex={0}
aria-label={`${label} ${index + 1}`}
/>
)
},
renderItem: (item: ReactNode) => {
return item
},
renderThumbs: (children: ReactNode | Array<ReactNode>) => {
const images = Children.map<ReactNode | undefined, ReactNode>(
children,
(item) => {
let img: ReactNode | undefined = item
// if the item is not an image, try to find the first image in the item's children.
if (
(item as React.ReactElement<{ children: ReactNode }>).type !== "img"
) {
img =
item &&
(
Children.toArray(
(
(item as React.ReactElement).props as {
children: ReactNode
}
).children,
) as ReactNode[]
).find(
(children) => (children as React.ReactElement).type === "img",
)
}
if (!img) {
return undefined
}
return img
},
)
if (images?.filter((image) => image).length === 0) {
console.warn(
`No images found! Can't build the thumb list without images. If you don't need thumbs, set showThumbs={false} in the Carousel. Note that it's not possible to get images rendered inside custom components.`,
)
return []
}
return images
},
statusFormatter: defaultStatusFormatter,
selectedItem: 0,
showArrows: true,
showIndicators: true,
showStatus: true,
showThumbs: true,
stopOnHover: true,
swipeScrollTolerance: 5,
swipeable: true,
transitionTime: 350,
verticalSwipe: "standard",
width: "100%",
animationHandler: "slide",
swipeAnimationHandler: slideSwipeAnimationHandler,
stopSwipingHandler: slideStopSwipingHandler,
}
constructor(props: CarouselProps) {
super(props)
const initState = {
initialized: false,
previousItem: props.selectedItem,
selectedItem: props.selectedItem,
hasMount: false,
isMouseEntered: false,
autoPlay: props.autoPlay,
swiping: false,
swipeMovementStarted: false,
cancelClick: false,
itemSize: 1,
itemListStyle: {},
slideStyle: {},
selectedStyle: {},
prevStyle: {},
}
this.animationHandler =
(typeof props.animationHandler === "function" &&
props.animationHandler) ||
(props.animationHandler === "fade" && fadeAnimationHandler) ||
slideAnimationHandler
this.state = {
...initState,
...this.animationHandler(props, initState),
}
}
componentDidMount() {
if (!this.props.children) {
return
}
this.setupCarousel()
}
componentDidUpdate(prevProps: CarouselProps, prevState: CarouselState) {
if (!prevProps.children && this.props.children && !this.state.initialized) {
this.setupCarousel()
}
if (!prevProps.autoFocus && this.props.autoFocus) {
this.forceFocus()
}
if (prevState.swiping && !this.state.swiping) {
// We stopped swiping, ensure we are heading to the new/current slide and not stuck
this.setState({
...this.props.stopSwipingHandler(this.props, this.state),
})
}
if (
prevProps.selectedItem !== this.props.selectedItem ||
prevProps.centerMode !== this.props.centerMode
) {
this.updateSizes()
this.moveTo(this.props.selectedItem)
}
if (prevProps.autoPlay !== this.props.autoPlay) {
if (this.props.autoPlay) {
this.setupAutoPlay()
} else {
this.destroyAutoPlay()
}
this.setState({ autoPlay: this.props.autoPlay })
}
}
componentWillUnmount() {
this.destroyCarousel()
}
setThumbsRef = (node: Thumbs) => {
this.thumbsRef = node
}
setCarouselWrapperRef = (node: HTMLDivElement) => {
this.carouselWrapperRef = node
}
setListRef = (node: HTMLElement | HTMLUListElement) => {
this.listRef = node
}
setItemsRef = (node: HTMLElement, index: number) => {
if (!this.itemsRef) {
this.itemsRef = []
}
this.itemsRef[index] = node
}
setupCarousel() {
this.bindEvents()
if (this.state.autoPlay && Children.count(this.props.children) > 1) {
this.setupAutoPlay()
}
if (this.props.autoFocus) {
this.forceFocus()
}
this.setState(
{
initialized: true,
},
() => {
const initialImage = this.getInitialImage()
if (initialImage && !initialImage.complete) {
// if it's a carousel of images, we set the mount state after the first image is loaded
initialImage.addEventListener("load", this.setMountState)
} else {
this.setMountState()
}
},
)
}
destroyCarousel() {
if (this.state.initialized) {
this.unbindEvents()
this.destroyAutoPlay()
}
}
setupAutoPlay() {
this.autoPlay()
const carouselWrapper = this.carouselWrapperRef
if (this.props.stopOnHover && carouselWrapper) {
carouselWrapper.addEventListener("mouseenter", this.stopOnHover)
carouselWrapper.addEventListener("mouseleave", this.startOnLeave)
}
}
destroyAutoPlay() {
this.clearAutoPlay()
const carouselWrapper = this.carouselWrapperRef
if (this.props.stopOnHover && carouselWrapper) {
carouselWrapper.removeEventListener("mouseenter", this.stopOnHover)
carouselWrapper.removeEventListener("mouseleave", this.startOnLeave)
}
}
bindEvents() {
// as the widths are calculated, we need to resize
// the carousel when the window is resized
window.addEventListener("resize", this.updateSizes)
// issue #2 - image loading smaller
window.addEventListener("DOMContentLoaded", this.updateSizes)
if (this.props.useKeyboardArrows) {
document.addEventListener("keydown", this.navigateWithKeyboard)
}
}
unbindEvents() {
// removing listeners
window.removeEventListener("resize", this.updateSizes)
window.removeEventListener("DOMContentLoaded", this.updateSizes)
const initialImage = this.getInitialImage()
if (initialImage) {
initialImage.removeEventListener("load", this.setMountState)
}
if (this.props.useKeyboardArrows) {
document.removeEventListener("keydown", this.navigateWithKeyboard)
}
}
autoPlay = () => {
if (Children.count(this.props.children) <= 1) {
return
}
this.clearAutoPlay()
if (!this.props.autoPlay) {
return
}
this.timer = setTimeout(() => {
this.increment()
}, this.props.interval)
}
clearAutoPlay = () => {
if (this.timer) clearTimeout(this.timer)
}
resetAutoPlay = () => {
this.clearAutoPlay()
this.autoPlay()
}
stopOnHover = () => {
this.setState({ isMouseEntered: true }, this.clearAutoPlay)
}
startOnLeave = () => {
this.setState({ isMouseEntered: false }, this.autoPlay)
}
forceFocus() {
this.carouselWrapperRef?.focus()
}
isFocusWithinTheCarousel = () => {
if (!this.carouselWrapperRef) {
return false
}
if (
document.activeElement === this.carouselWrapperRef ||
this.carouselWrapperRef.contains(document.activeElement)
) {
return true
}
return false
}
navigateWithKeyboard = (e: KeyboardEvent) => {
if (!this.isFocusWithinTheCarousel()) {
return
}
const { axis } = this.props
const isHorizontal = axis === "horizontal"
const keyNames = {
ArrowUp: 38,
ArrowRight: 39,
ArrowDown: 40,
ArrowLeft: 37,
}
const nextKey = isHorizontal ? keyNames.ArrowRight : keyNames.ArrowDown
const prevKey = isHorizontal ? keyNames.ArrowLeft : keyNames.ArrowUp
if (nextKey === e.keyCode) {
this.increment()
} else if (prevKey === e.keyCode) {
this.decrement()
}
}
updateSizes = () => {
if (
!this.state.initialized ||
!this.itemsRef ||
this.itemsRef.length === 0
) {
return
}
const isHorizontal = this.props.axis === "horizontal"
const firstItem = this.itemsRef[0]
if (!firstItem) {
return
}
const itemSize = isHorizontal
? firstItem.clientWidth
: firstItem.clientHeight
this.setState({
itemSize,
})
if (this.thumbsRef) {
this.thumbsRef.updateSizes()
}
}
setMountState = () => {
this.setState({ hasMount: true })
this.updateSizes()
}
handleClickItem = (index: number, item: React.ReactNode) => {
if (Children.count(this.props.children) === 0) {
return
}
if (this.state.cancelClick) {
this.setState({
cancelClick: false,
})
return
}
this.props.onClickItem(index, item)
if (index !== this.state.selectedItem) {
this.setState({
selectedItem: index,
})
}
}
/**
* On Change handler, Passes the index and React node to the supplied onChange prop
* @param index of the carousel item
* @param item React node of the item being changed
*/
handleOnChange = (index: number, item: React.ReactNode) => {
if (Children.count(this.props.children) <= 1) {
return
}
this.props.onChange(index, item)
}
handleClickThumb = (index: number, item: React.ReactNode) => {
this.props.onClickThumb(index, item)
this.moveTo(index)
}
onSwipeStart = (event: React.TouchEvent) => {
this.setState({
swiping: true,
})
this.props.onSwipeStart(event)
}
onSwipeEnd = (event: React.TouchEvent) => {
this.setState({
swiping: false,
cancelClick: false,
swipeMovementStarted: false,
})
this.props.onSwipeEnd(event)
this.clearAutoPlay()
if (this.state.autoPlay) {
this.autoPlay()
}
}
onSwipeMove = (delta: { x: number; y: number }, event: React.TouchEvent) => {
this.props.onSwipeMove(event)
const animationHandlerResponse = this.props.swipeAnimationHandler(
delta,
this.props,
this.state,
this.setState.bind(this),
)
this.setState({
...animationHandlerResponse,
})
// If we have not moved, we should have an empty object returned
// Return false to allow scrolling when not swiping
return !!Object.keys(animationHandlerResponse).length
}
/**
* Decrements the selectedItem index a number of positions through the children list
* @param positions
* @param fromSwipe
*/
decrement = (positions = 1) => {
this.moveTo(
this.state.selectedItem - (typeof positions === "number" ? positions : 1),
)
}
/**
* Increments the selectedItem index a number of positions through the children list
* @param positions
* @param fromSwipe
*/
increment = (positions = 1) => {
this.moveTo(
this.state.selectedItem + (typeof positions === "number" ? positions : 1),
)
}
/**
* Moves the selected item to the position provided
* @param position
* @param fromSwipe
*/
moveTo = (position?: number) => {
if (typeof position !== "number") {
return
}
const lastPosition = Children.count(this.props.children) - 1
if (position < 0) {
position = this.props.infiniteLoop ? lastPosition : 0
}
if (position > lastPosition) {
position = this.props.infiniteLoop ? 0 : lastPosition
}
this.selectItem({
// if it's not a slider, we don't need to set position here
selectedItem: position,
})
// don't reset auto play when stop on hover is enabled, doing so will trigger a call to auto play more than once
// and will result in the interval function not being cleared correctly.
if (this.state.autoPlay && this.state.isMouseEntered === false) {
this.resetAutoPlay()
}
}
onClickNext = () => {
this.increment(1)
}
onClickPrev = () => {
this.decrement(1)
}
onSwipeForward = () => {
this.increment(1)
if (this.props.emulateTouch) {
this.setState({ cancelClick: true })
}
}
onSwipeBackwards = () => {
this.decrement(1)
if (this.props.emulateTouch) {
this.setState({ cancelClick: true })
}
}
changeItem =
(newIndex: number) => (e: React.MouseEvent | React.KeyboardEvent) => {
if (!isKeyboardEvent(e) || e.key === "Enter") {
this.moveTo(newIndex)
}
}
/**
* This function is called when you want to 'select' a new item, or rather move to a 'selected' item
* It also handles the onChange callback wrapper
* @param state state object with updated selected item, and swiping bool if relevant
*/
selectItem = (state: Pick<CarouselState, "selectedItem" | "swiping">) => {
// Merge in the new state while updating updating previous item
this.setState(
{
previousItem: this.state.selectedItem,
...state,
},
() => {
// Run animation handler and update styles based on it
this.setState(this.animationHandler(this.props, this.state))
},
)
this.handleOnChange(
state.selectedItem,
Children.toArray(this.props.children)[state.selectedItem],
)
}
getInitialImage = () => {
const selectedItem = this.props.selectedItem
const item = this.itemsRef && this.itemsRef[selectedItem]
const images = (item && item.getElementsByTagName("img")) || []
return images[0]
}
getVariableItemHeight = (position: number) => {
const item = this.itemsRef && this.itemsRef[position]
if (this.state.hasMount && item && item.children.length) {
const slideImages = item.children[0].getElementsByTagName("img") || []
if (slideImages.length > 0) {
const image = slideImages[0]
if (!image.complete) {
// if the image is still loading, the size won't be available so we trigger a new render after it's done
const onImageLoad = () => {
this.forceUpdate()
image.removeEventListener("load", onImageLoad)
}
image.addEventListener("load", onImageLoad)
}
}
// try to get img first, if img not there find first display tag
const displayItem = slideImages[0] || item.children[0]
const height = displayItem.clientHeight
return height > 0 ? height : null
}
return null
}
renderItems(isClone?: boolean) {
if (!this.props.children) {
return []
}
return Children.map(this.props.children, (item, index) => {
const isSelected = index === this.state.selectedItem
const isPrevious = index === this.state.previousItem
let style: React.CSSProperties =
(isSelected && this.state.selectedStyle) ||
(isPrevious && this.state.prevStyle) ||
this.state.slideStyle ||
{}
if (this.props.centerMode && this.props.axis === "horizontal") {
style = { ...style, minWidth: this.props.centerSlidePercentage + "%" }
}
if (this.state.swiping && this.state.swipeMovementStarted) {
style = { ...style, pointerEvents: "none" }
}
const slideProps = {
ref: (e: HTMLLIElement) => this.setItemsRef(e, index),
key: "itemKey" + index + (isClone ? "clone" : ""),
className: klass.ITEM(
true,
index === this.state.selectedItem,
index === this.state.previousItem,
),
onClick: this.handleClickItem.bind(this, index, item),
style,
}
return (
<li {...slideProps}>
{this.props.renderItem(item, {
isSelected: index === this.state.selectedItem,
isPrevious: index === this.state.previousItem,
})}
</li>
)
})
}
renderControls() {
const { showIndicators, labels, renderIndicator, children } = this.props
if (!showIndicators) {
return null
}
return (
<ul className="control-dots">
{Children.map(children, (_, index) => {
return (
renderIndicator &&
renderIndicator(
this.changeItem(index),
index === this.state.selectedItem,
index,
labels.item,
)
)
})}
</ul>
)
}
renderStatus() {
if (!this.props.showStatus) {
return null
}
return (
<p className="carousel-status">
{this.props.statusFormatter(
this.state.selectedItem + 1,
Children.count(this.props.children),
)}
</p>
)
}
renderThumbs() {
if (
!this.props.showThumbs ||
!this.props.children ||
Children.count(this.props.children) === 0
) {
return null
}
return (
<Thumbs
ref={this.setThumbsRef}
onSelectItem={this.handleClickThumb}
selectedItem={this.state.selectedItem}
transitionTime={this.props.transitionTime}
thumbWidth={this.props.thumbWidth}
labels={this.props.labels}
emulateTouch={this.props.emulateTouch}
>
{this.props.renderThumbs(this.props.children)}
</Thumbs>
)
}
render() {
if (!this.props.children || Children.count(this.props.children) === 0) {
return null
}
const isSwipeable =
this.props.swipeable && Children.count(this.props.children) > 1
const isHorizontal = this.props.axis === "horizontal"
const canShowArrows =
this.props.showArrows && Children.count(this.props.children) > 1
// show left arrow?
const hasPrev =
(canShowArrows &&
(this.state.selectedItem > 0 || this.props.infiniteLoop)) ||
false
// show right arrow
const hasNext =
(canShowArrows &&
(this.state.selectedItem < Children.count(this.props.children) - 1 ||
this.props.infiniteLoop)) ||
false
const itemsClone = this.renderItems(true)
const firstClone = itemsClone?.shift()
const lastClone = itemsClone?.pop()
let swiperProps: SwiperProps = {
className: klass.SLIDER(true, this.state.swiping),
onSwipeMove: this.onSwipeMove,
onSwipeStart: this.onSwipeStart,
onSwipeEnd: this.onSwipeEnd,
style: this.state.itemListStyle || {},
tolerance: this.props.swipeScrollTolerance,
}
const containerStyles: React.CSSProperties = {}
if (isHorizontal) {
swiperProps.onSwipeLeft = this.onSwipeForward
swiperProps.onSwipeRight = this.onSwipeBackwards
if (this.props.dynamicHeight) {
const itemHeight = this.getVariableItemHeight(this.state.selectedItem)
// swiperProps.style.height = itemHeight || 'auto';
containerStyles.height = itemHeight || "auto"
}
} else {
swiperProps.onSwipeUp =
this.props.verticalSwipe === "natural"
? this.onSwipeBackwards
: this.onSwipeForward
swiperProps.onSwipeDown =
this.props.verticalSwipe === "natural"
? this.onSwipeForward
: this.onSwipeBackwards
swiperProps.style = { ...swiperProps.style, height: this.state.itemSize }
containerStyles.height = this.state.itemSize
}
return (
<div
aria-label={this.props.ariaLabel}
className={`ar-Carousel ${klass.ROOT(this.props.className)}${
this.props.classes ? " " + this.props.classes : ""
}`}
ref={this.setCarouselWrapperRef}
tabIndex={this.props.useKeyboardArrows ? 0 : undefined}
>
<div
className={klass.CAROUSEL(true)}
style={{ width: this.props.width }}
>
{!this.props.noMarkers && this.renderControls()}
{this.props.renderArrowPrev(
this.onClickPrev,
hasPrev,
this.props.labels.leftArrow,
)}
<div
className={klass.WRAPPER(true, this.props.axis)}
style={containerStyles}
>
{isSwipeable ? (
<Swiper
tagName="ul"
innerRef={this.setListRef}
{...swiperProps}
allowMouseEvents={this.props.emulateTouch}
>
{this.props.infiniteLoop && lastClone}
{this.renderItems()}
{this.props.infiniteLoop && firstClone}
</Swiper>
) : (
<ul
className={klass.SLIDER(true, this.state.swiping)}
ref={(node: HTMLUListElement) => this.setListRef(node)}
style={this.state.itemListStyle || {}}
>
{this.props.infiniteLoop && lastClone}
{this.renderItems()}
{this.props.infiniteLoop && firstClone}
</ul>
)}
</div>
{this.props.renderArrowNext(
this.onClickNext,
hasNext,
this.props.labels.rightArrow,
)}
{this.renderStatus()}
</div>
{this.renderThumbs()}
</div>
)
}
}

View File

@@ -1,15 +1,17 @@
import { ArPillSizes, BasicFilterConfig, BasicFilterType } from "@armco/types"
import { ReactNode } from "react"
import { ArPillSizes } from "./enums"
import { BasicFilterConfig, BasicFilterType } from "@armco/types"
import { toCamelCase } from "@armco/utils/helper"
import SelectionPill from "./SelectionPill"
import "./CategoryFilter.component.scss"
interface CategoryFilterProps {
export interface CategoryFilterProps {
categoryGroups: { [key: string]: { [key: string]: Array<string> } }
currentCategoryFilters?: { [key: string]: Array<BasicFilterConfig> }
onFilterChange: Function
}
const CategoryFilter = (props: CategoryFilterProps): JSX.Element => {
const CategoryFilter = (props: CategoryFilterProps): ReactNode => {
const { categoryGroups, currentCategoryFilters, onFilterChange } = props
const onCategorySelection = (

View File

@@ -1,9 +1,17 @@
import { useState } from "react"
import { CheckboxProps } from "@armco/types"
import { ReactNode, useState } from "react"
import { CheckBoxTypes, FunctionType } from "@armco/types"
import { FormInputProps } from "./types"
import Toggle from "./Toggle"
import "./Checkbox.component.scss"
const Checkbox = (props: CheckboxProps): JSX.Element => {
export interface CheckboxProps extends FormInputProps {
id?: string
label?: string
type?: CheckBoxTypes
onChange: FunctionType
}
const Checkbox = (props: CheckboxProps): ReactNode => {
const { classes, label, id, onChange } = props
const [checked, setChecked] = useState<boolean>()
const { type, ...toggleProps } = props

View File

@@ -1,5 +1,12 @@
import { ReactElement, ReactNode } from "react"
import { ChunkProps } from "@armco/types"
import { TextFormat } from "@armco/types"
import { BaseProps } from "./types"
export interface ChunkProps extends BaseProps {
id: string
text: string
formats: TextFormat
}
const Chunk = (props: ChunkProps): ReactNode => {
const { id, text, formats } = props

View File

@@ -1,9 +1,16 @@
import { useState } from "react"
import { ColorPickerProps } from "@armco/types"
import { ReactNode, useState } from "react"
import { BaseProps } from "./types"
import { generateRandomId } from "@armco/utils/helper"
import "./ColorPicker.component.scss"
const ColorPicker = (props: ColorPickerProps): JSX.Element => {
export interface ColorPickerProps extends BaseProps {
id?: string
label?: string
onChange?: Function
value?: string
}
const ColorPicker = (props: ColorPickerProps): ReactNode => {
const { id, label, onChange, value: externalValue } = props
const [value, setValue] = useState<string | undefined>(externalValue)
const idFinal = id || generateRandomId()

View File

@@ -1,9 +1,16 @@
import { useState } from "react"
import { ColorSelectorProps } from "@armco/types"
import { ReactNode, useState } from "react"
import { FunctionType } from "@armco/types"
import { BaseProps } from "./types"
import TextInput from "./TextInput"
import "./ColorSelector.component.scss"
const ColorSelector = (props: ColorSelectorProps): JSX.Element => {
export interface ColorSelectorProps extends BaseProps {
label?: string
onChange?: FunctionType
withSample?: boolean
}
const ColorSelector = (props: ColorSelectorProps): ReactNode => {
const { classes, label, onChange, withSample } = props
const [iconColor, setIconColor] = useState<string>()
@@ -37,16 +44,15 @@ const ColorSelector = (props: ColorSelectorProps): JSX.Element => {
<div className="ar-ColorSelector w-100">
{label && <div className="mb-3 fw-bold text-center">{label}</div>}
<ul
className={`ar-ColorSelector__list d-flex flex-column list-unstyled${
classes ? " " + classes : ""
}`}
className={`ar-ColorSelector__list d-flex flex-column list-unstyled${classes ? " " + classes : ""
}`}
style={{ height: label ? "calc(100% - 2rem)" : "100%" }}
>
{selectors}
<TextInput
classes="ar-ColorSelector__picker"
type="color"
onChange={(e) => onColorChange((e.target as HTMLInputElement).value)}
onChange={(e: any) => onColorChange((e.target as HTMLInputElement).value)}
/>
</ul>
{withSample && (

View File

@@ -1,8 +1,14 @@
import { Component_404Props } from "@armco/types"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import Icon from "@armco/icon"
import "./Component_404.component.scss"
const Component_404 = (props: Component_404Props): JSX.Element => {
export interface Component_404Props extends BaseProps {
iconSize?: string
}
const Component_404 = (props: Component_404Props): ReactNode => {
const { iconSize } = props
return (
<div className="ar-Component_404 flex-center h-100">

View File

@@ -1,9 +1,9 @@
import React from "react"
import { ReactNode } from "react"
import "./Contact.component.scss"
interface ContactProps {}
export interface ContactProps { }
const Contact = (props: any): JSX.Element => {
const Contact = (props: ContactProps): ReactNode => {
return (
<div className="ar-Contact">
In Component Contact

View File

@@ -1,12 +1,12 @@
import { ReactNode } from "react"
import "./Content.component.scss"
interface ContentProps {
export interface ContentProps {
children?: ReactNode
classes?: string
}
const Content = (props: ContentProps): JSX.Element => {
const Content = (props: ContentProps): ReactNode => {
const { children, classes } = props
return (
<div className={`ar-Content flex-grow-1${classes ? " " + classes : ""}`}>

View File

@@ -1,9 +1,14 @@
import { useEffect, useRef, useState } from "react"
import { ContextMenuProps } from "@armco/types"
import { ReactNode, useEffect, useRef, useState } from "react"
import { BaseProps } from "./types"
import InlineMenu from "./InlineMenu"
import "./ContextMenu.component.scss"
const ContextMenu = (props: ContextMenuProps): JSX.Element => {
export interface ContextMenuProps extends BaseProps {
children?: ReactNode
data: { [key: string]: any }
}
const ContextMenu = (props: ContextMenuProps): ReactNode => {
const { children, classes, data, demo, style } = props
const [clickCoordinates, setClickCoordinates] = useState<{
[key: string]: number

View File

@@ -1,9 +1,9 @@
import React from "react"
import { ReactNode } from "react"
import "./Cookies.component.scss"
interface CookiesProps {}
export interface CookiesProps { }
const Cookies = (props: any): JSX.Element => {
const Cookies = (props: CookiesProps): ReactNode => {
return (
<div className="ar-Cookies">
In Component Cookies

View File

@@ -1,11 +1,17 @@
import { ChangeEvent, useEffect, useState } from "react"
import { CronTabProps, FunctionType } from "@armco/types"
import { ChangeEvent, ReactNode, useEffect, useState } from "react"
import { FunctionType, ObjectType } from "@armco/types"
import Icon from "@armco/icon"
import { BaseProps } from "./types"
import TextInput from "./TextInput"
import "./CronTab.component.scss"
export interface CronTabProps extends BaseProps {
onChange: FunctionType
value?: ObjectType | string
}
const cronFields = ["min", "hour", "day", "week", "month"]
const CronTab = (props: CronTabProps): JSX.Element => {
const CronTab = (props: CronTabProps): ReactNode => {
const { onChange, value } = props
const [cronTab, setCronTab] = useState<{ [key: string]: string }>({})
const [helpExpanded, toggleHelpExpanded] = useState<boolean>()

View File

@@ -1,9 +1,9 @@
import React from "react"
import { ReactNode } from "react"
import "./Cta.component.scss"
interface CtaProps {}
export interface CtaProps { }
const Cta = (props: any): JSX.Element => {
const Cta = (props: CtaProps): ReactNode => {
return (
<div className="ar-Cta">
In Component Cta

View File

@@ -1,9 +1,10 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Dashboard.component.scss"
interface DashboardProps {}
export interface DashboardProps extends BaseProps { }
const Dashboard = (props: any): JSX.Element => {
const Dashboard = (props: DashboardProps): ReactNode => {
return (
<div className="ar-Dashboard">
In Component Dashboard

View File

@@ -1,8 +1,13 @@
import { ReactNode } from "react"
import { useEffect, useState } from "react"
import { DateInputProps } from "@armco/types"
import { FormInputProps } from "./types"
import "./DateInput.component.scss"
const DateInput = (props: DateInputProps): JSX.Element => {
export interface DateInputProps extends FormInputProps {
placeholder?: string
}
const DateInput = (props: DateInputProps): ReactNode => {
const {
classes,
containerClasses,
@@ -20,24 +25,21 @@ const DateInput = (props: DateInputProps): JSX.Element => {
return (
<div
className={`ar-DateInput${
containerClasses ? " " + containerClasses : ""
}`}
className={`ar-DateInput${containerClasses ? " " + containerClasses : ""
}`}
>
{label && (
<label
className={`ar-DateInput__label${
labelClasses ? " " + labelClasses : ""
}`}
className={`ar-DateInput__label${labelClasses ? " " + labelClasses : ""
}`}
htmlFor={id}
>
{label}
</label>
)}
<input
className={`ar-DateInput__picker form-component p-2${
classes ? " " + classes : ""
}`}
className={`ar-DateInput__picker form-component p-2${classes ? " " + classes : ""
}`}
id={id}
onChange={(e) => setLocalValue(e.target.value)}
placeholder={placeholder}

View File

@@ -1,7 +1,10 @@
import { DetailsPanelProps } from "@armco/types"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./DetailsPanel.component.scss"
const DetailsPanel = (props: DetailsPanelProps): JSX.Element => {
export interface DetailsPanelProps extends BaseProps { }
const DetailsPanel = (props: DetailsPanelProps): ReactNode => {
return <div className="ar-DetailsPanel">In Component DetailsPanel</div>
}

View File

@@ -1,7 +1,10 @@
import { DialogProps } from "@armco/types"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Dialog.component.scss"
const Dialog = (props: DialogProps): JSX.Element => {
export interface DialogProps extends BaseProps { }
const Dialog = (props: DialogProps): ReactNode => {
return <div className="ar-Dialog">In Component Dialog</div>
}

View File

@@ -1,9 +1,10 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Download.component.scss"
interface DownloadProps {}
export interface DownloadProps extends BaseProps { }
const Download = (props: any): JSX.Element => {
const Download = (props: DownloadProps): ReactNode => {
return (
<div className="ar-Download">
In Component Download

View File

@@ -1,16 +1,17 @@
import {
import React, {
Children,
MutableRefObject,
RefObject,
ReactElement,
cloneElement,
forwardRef,
useEffect,
useRef,
Ref,
} from "react"
import { findDOMNode } from "react-dom"
import { useDrag } from "react-dnd"
import { getEmptyImage } from "react-dnd-html5-backend"
import { ArDndItemTypes, DraggableProps } from "@armco/types"
import { ArDndItemTypes } from "./enums"
import { BaseProps } from "./types"
import "./Draggable.component.scss"
const dummyChildren = (
@@ -19,6 +20,15 @@ const dummyChildren = (
></div>
)
export interface DraggableProps extends BaseProps {
itemType?: ArDndItemTypes | string
canDrag?: boolean
itemData?: any
hideDefaultPreview?: boolean
}
const Draggable = forwardRef((props: DraggableProps, ref) => {
const {
canDrag,
@@ -30,7 +40,8 @@ const Draggable = forwardRef((props: DraggableProps, ref) => {
} = props
const localRef = useRef(null)
ref = ref || localRef
const dragRef = (ref || localRef) as RefObject<HTMLElement>
let firstChild
if (typeof children === "string") {
firstChild = <span>{children}</span>
@@ -58,36 +69,67 @@ const Draggable = forwardRef((props: DraggableProps, ref) => {
)
useEffect(() => {
const node = findDOMNode((ref as MutableRefObject<HTMLElement>).current)
const node = dragRef.current
if (node && node.nodeType === Node.ELEMENT_NODE) {
drag(node as Element)
}
}, [drag])
}, [drag, dragRef])
useEffect(() => {
if (hideDefaultPreview && preview) {
preview(getEmptyImage(), { captureDraggingState: true })
}
}, [hideDefaultPreview, preview])
if (hideDefaultPreview && preview) {
preview(getEmptyImage(), { captureDraggingState: true })
}
}, [hideDefaultPreview, preview])
const {
style: childStyles,
className: childClasses,
...restProps
} = (firstChild as ReactElement)?.props || {}
} = (firstChild as ReactElement<any>)?.props || {}
// Clone the first child and attach the drag function to it
return cloneElement(firstChild as ReactElement, {
ref,
style: {
cursor: "move",
opacity: isDragging ? 0.5 : 1,
...(style || {}),
...(childStyles || {}),
},
className: `ar-Draggable ${childClasses || ""}`.trim(),
...(restProps || {}),
})
// Helper to ensure only plain style objects are merged
function toPlainStyle(styleObj: any): { [key: string]: string } {
if (!styleObj) return {}
// If it's a CSSStyleDeclaration, convert to plain object
if (typeof styleObj.getPropertyValue === 'function') {
const plain: { [key: string]: string } = {}
for (let i = 0; i < styleObj.length; i++) {
const key = styleObj[i]
plain[key] = styleObj.getPropertyValue(key)
}
return plain
}
return styleObj as { [key: string]: string }
}
const isDOMElement = typeof (firstChild as any)?.type === "string"
const mergedStyle = {
...toPlainStyle(childStyles),
...toPlainStyle(style),
cursor: "move",
opacity: isDragging ? 0.5 : 1,
} as React.CSSProperties
if (isDOMElement) {
return cloneElement(firstChild as ReactElement<any>, {
ref: dragRef,
style: mergedStyle,
className: `ar-Draggable ${childClasses || ""}`.trim(),
...(restProps || {}),
})
} else {
const spanRef: Ref<HTMLSpanElement> = dragRef as Ref<HTMLSpanElement>
return (
<span
ref={spanRef}
style={mergedStyle}
className={`ar-Draggable ${childClasses || ""}`.trim()}
{...restProps}
>
{firstChild}
</span>
)
}
})
export default Draggable

View File

@@ -1,14 +1,23 @@
import { useEffect, useRef } from "react"
import { ArThemes, DrawerProps } from "@armco/types"
import { ReactNode, useEffect, useRef } from "react"
import { useDrawerState, useSlotted, useTheme } from "@armco/utils/hooks"
import { isMobile as checkMobile } from "@armco/utils/helper"
import Icon from "@armco/icon"
import { ArThemes } from "./enums"
import { BaseProps } from "./types"
import "./Drawer.component.scss"
export interface DrawerProps extends BaseProps {
children?: ReactNode
collapsed?: boolean
contentClasses?: string
isCollapsible?: boolean
title?: string
}
const isMobile = checkMobile()
let clickedSelf: boolean
const Drawer = (props: DrawerProps): JSX.Element => {
const Drawer = (props: DrawerProps): ReactNode => {
const { children, classes, contentClasses, isCollapsible, title } = props
const drawerRef = useRef<HTMLDivElement>(null)
const { drawerState, setDrawerState } = useDrawerState()
@@ -25,11 +34,9 @@ const Drawer = (props: DrawerProps): JSX.Element => {
return (
<aside
className={`ar-Drawer overflow-auto d-flex flex-column${
classes ? " " + classes : ""
}${isCollapsible ? " position-relative" : ""}${
drawerState?.collapsed ? " collapsed" : ""
}${title ? " has-title" : ""}`}
className={`ar-Drawer overflow-auto d-flex flex-column${classes ? " " + classes : ""
}${isCollapsible ? " position-relative" : ""}${drawerState?.collapsed ? " collapsed" : ""
}${title ? " has-title" : ""}`}
tabIndex={-1}
ref={drawerRef}
onMouseDown={() => {
@@ -71,9 +78,8 @@ const Drawer = (props: DrawerProps): JSX.Element => {
</div>
)}
<div
className={`ar-Drawer__content${
contentClasses ? " " + contentClasses : ""
}`}
className={`ar-Drawer__content${contentClasses ? " " + contentClasses : ""
}`}
>
{!drawerState?.collapsed && children}
</div>

View File

@@ -1,4 +1,7 @@
import { ReactNode } from "react"
import { useEffect, useState } from "react"
import { FunctionType, OptionType, PRIMITIVES } from "@armco/types"
import Icon from "@armco/icon"
import {
ArButtonVariants,
ArDropdownVariants,
@@ -6,11 +9,8 @@ import {
ArPopoverPositions,
ArPopoverSlots,
ArThemes,
DropdownProps,
OptionType,
PRIMITIVES,
} from "@armco/types"
import Icon from "@armco/icon"
} from "./enums"
import { FormInputProps } from "./types"
import Button from "./Button"
import List from "./List"
import Pill from "./Pill"
@@ -25,7 +25,28 @@ const demoOptions: Array<OptionType> = [
{ label: "Chennai", name: "Chennai", value: "CH" },
]
const Dropdown = (props: DropdownProps): JSX.Element => {
export interface DropdownProps extends FormInputProps {
anchorClasses?: string
contentClasses?: string
contentMatchAnchorWidth?: boolean
context?: string
hasBorder?: boolean
hideDropdownMarker?: boolean
id?: string
isMultiSelect?: boolean
label?: string
onSelectionChanged: FunctionType
options?: Array<OptionType>
placeholder?: string
selected?: Array<PRIMITIVES>
showCheckBoxes?: boolean
stretch?: boolean
subtitle?: string
variant?: ArDropdownVariants
}
const Dropdown = (props: DropdownProps): ReactNode => {
const {
assistiveContent,
anchorClasses,
@@ -166,8 +187,8 @@ const Dropdown = (props: DropdownProps): JSX.Element => {
const assistiveContentRender = assistiveContent ? (
typeof assistiveContent === "object" &&
"content" in assistiveContent &&
"onClick" in assistiveContent ? (
"content" in assistiveContent &&
"onClick" in assistiveContent ? (
<Button
classes="mb-2 p-0 f3"
variant={ArButtonVariants.LINK}
@@ -201,18 +222,15 @@ const Dropdown = (props: DropdownProps): JSX.Element => {
stretch
>
<span
className={`ar-Dropdown__input-and-selections d-inline-flex cursor-pointer flex-v-center${
anchorClasses ? " " + anchorClasses : ""
}${stretch ? " w-100" : ""}`}
className={`ar-Dropdown__input-and-selections d-inline-flex cursor-pointer flex-v-center${anchorClasses ? " " + anchorClasses : ""
}${stretch ? " w-100" : ""}`}
slot={ArPopoverSlots.ANCHOR}
>
{hasBorder ? (
<span
className={`ar-Dropdown__selection-anchor form-component p-2 d-inline-flex justify-content-between fw-bold h-100${
!isMultiSelect && hasBorder ? " flex-center" : " flex-v-center"
}${context === "search" ? " border-right-0" : ""}${
stretch ? " w-100" : ""
}`}
className={`ar-Dropdown__selection-anchor form-component p-2 d-inline-flex justify-content-between fw-bold h-100${!isMultiSelect && hasBorder ? " flex-center" : " flex-v-center"
}${context === "search" ? " border-right-0" : ""}${stretch ? " w-100" : ""
}`}
>
{variant === ArDropdownVariants.SELECTIONSASPILLS ? (
pillsRender
@@ -266,9 +284,8 @@ const Dropdown = (props: DropdownProps): JSX.Element => {
)}
</span>
<div
className={`ar-Dropdown__options w-100${
contentClasses ? " " + contentClasses : ""
}`}
className={`ar-Dropdown__options w-100${contentClasses ? " " + contentClasses : ""
}`}
slot={ArPopoverSlots.POPOVER}
>
<List
@@ -277,12 +294,12 @@ const Dropdown = (props: DropdownProps): JSX.Element => {
data={
localOptions
? localOptions.map((option) => ({
label: option.label as string,
name: option.name,
value: option.value,
isSelected: option.isSelected,
onClick: onLocalChange,
}))
label: option.label as string,
name: option.name,
value: option.value,
isSelected: option.isSelected,
onClick: onLocalChange,
}))
: []
}
theme={theme}
@@ -293,21 +310,17 @@ const Dropdown = (props: DropdownProps): JSX.Element => {
const labelRender = (
<div
className={`ar-TextInput__label-container${
isLabelLR
? ` flex-v-center${
labelPlacement === ArPlacement.LEFT ? " me-3" : ""
}`
: ""
}`}
className={`ar-TextInput__label-container${isLabelLR
? ` flex-v-center${labelPlacement === ArPlacement.LEFT ? " me-3" : ""
}`
: ""
}`}
>
<div className="ar-TextInput__label-container__label-assistive-text flex-v-center justify-content-between">
<label
className={`ar-TextInput__label h-100 fw-bold${
labelClasses ? " " + labelClasses : ""
}${required ? " required" : ""}${
subtitle || isLabelLR ? "" : " mb-2"
}`}
className={`ar-TextInput__label h-100 fw-bold${labelClasses ? " " + labelClasses : ""
}${required ? " required" : ""}${subtitle || isLabelLR ? "" : " mb-2"
}`}
htmlFor={id}
>
{label}
@@ -367,11 +380,9 @@ const Dropdown = (props: DropdownProps): JSX.Element => {
return (
<div
className={`ar-Dropdown d-inline-flex${classes ? " " + classes : ""}${
size ? " " + size : ""
}${variant ? " " + variant : ""}${
isDisabled ? " disabled pointer-events-none" : ""
} ${flexClass}`}
className={`ar-Dropdown d-inline-flex${classes ? " " + classes : ""}${size ? " " + size : ""
}${variant ? " " + variant : ""}${isDisabled ? " disabled pointer-events-none" : ""
} ${flexClass}`}
id={id}
>
{contentRender}

View File

@@ -1,18 +1,27 @@
import { findDOMNode } from "react-dom"
import {
Children,
cloneElement,
ForwardedRef,
forwardRef,
MutableRefObject,
isValidElement,
ReactElement,
useEffect,
useRef,
RefObject,
} from "react"
import { useDrop } from "react-dnd"
import { ArDndItemTypes, DroppableProps } from "@armco/types"
import { FunctionType } from "@armco/types"
import { ArDndItemTypes } from "./enums"
import { BaseProps } from "./types"
import "./Droppable.component.scss"
export interface DroppableProps extends BaseProps {
acceptTypes?: ArDndItemTypes | string | Array<string | ArDndItemTypes>
dropHandler: FunctionType
canDrop?: FunctionType
hideHoverEffect?: boolean
}
const Droppable = forwardRef(
(props: DroppableProps, ref: ForwardedRef<HTMLElement>) => {
const {
@@ -23,8 +32,8 @@ const Droppable = forwardRef(
hideHoverEffect,
style,
} = props
const localRef = useRef(null)
ref = ref || localRef
const localRef = useRef<HTMLElement | null>(null)
const dropRef = (ref as RefObject<HTMLElement>) || localRef
// Convert children to an array and use the first child
const childrenArray = Children.toArray(children)
const firstChild = childrenArray[0]
@@ -50,33 +59,47 @@ const Droppable = forwardRef(
)
useEffect(() => {
const node = findDOMNode((ref as MutableRefObject<HTMLElement>).current)
const node = dropRef.current
if (node && node.nodeType === Node.ELEMENT_NODE) {
drop(node as Element)
}
}, [drop])
}, [drop, dropRef])
const {
style: childStyles,
className: childClasses,
...restProps
} = (firstChild as ReactElement)?.props || {}
// Clone the first child and attach the drop function to it
return firstChild
? cloneElement(firstChild as ReactElement, {
ref,
style: {
...(style || {}),
...(childStyles || {}),
},
className: `ar-Droppable ${childClasses || ""} ${
isOver ? "drag-over" : ""
}${hideHoverEffect ? " hide-hover-effect" : ""}`.trim(),
onDragOver: (e: any) => e.preventDefault(),
...(restProps || {}),
})
: null
let childProps: any = {}
let childStyles = {}
let childClasses = ""
let restProps = {}
if (
isValidElement(firstChild) &&
typeof (firstChild as any).type === "string"
) {
const {
style: cs,
className: cc,
...rest
} = (firstChild as ReactElement<any>).props || {}
childStyles = cs || {}
childClasses = cc || ""
restProps = rest
childProps = {
ref: dropRef,
style: {
...(style || {}),
...childStyles,
},
className: `ar-Droppable ${childClasses} ${isOver ? "drag-over" : ""}${hideHoverEffect ? " hide-hover-effect" : ""}`.trim(),
onDragOver: (e: any) => e.preventDefault(),
...restProps,
}
} else if (isValidElement(firstChild)) {
// For non-DOM elements, only pass restProps and onDragOver
const { ...rest } = (firstChild as ReactElement<any>).props || {}
childProps = {
onDragOver: (e: any) => e.preventDefault(),
...rest,
}
}
return firstChild ? cloneElement(firstChild as ReactElement, childProps) : null
},
)

View File

@@ -1,20 +1,29 @@
/* eslint-disable react/jsx-pascal-case */
import { lazy, ReactNode, Suspense, useEffect, useState } from "react"
import { NativeTypes } from "react-dnd-html5-backend"
import { FunctionType, ObjectType, TreeListData } from "@armco/types"
import Icon from "@armco/icon"
import {
ArContentTypes,
ArDndItemTypes,
ArLoaderTypes,
DroppableContainerProps,
TreeListData,
} from "@armco/types"
import Icon from "@armco/icon"
} from "./enums"
import { BaseProps } from "./types"
import Loader from "./Loader"
import Droppable from "./Droppable"
import Component_404 from "./Component_404"
import "./DroppableContainer.component.scss"
const DroppableContainer = (props: DroppableContainerProps): JSX.Element => {
export interface DroppableContainerProps extends BaseProps {
allowedDropCount?: number
dropHandler?: FunctionType
placeholder?: ReactNode
placeholderProps?: ObjectType
placeholderType?: ArContentTypes
}
const DroppableContainer = (props: DroppableContainerProps): ReactNode => {
const {
allowedDropCount = 1,
classes,
@@ -111,9 +120,8 @@ const DroppableContainer = (props: DroppableContainerProps): JSX.Element => {
dropHandler={dropHandler}
>
<div
className={`ar-DroppableContainer${classes ? " " + classes : ""}${
children ? "" : " bg border"
}`}
className={`ar-DroppableContainer${classes ? " " + classes : ""}${children ? "" : " bg border"
}`}
style={{
minWidth: children ? "auto" : "10rem",
minHeight: children ? "auto" : "10rem",

View File

@@ -1,9 +1,10 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./EcommOrders.component.scss"
interface EcommOrdersProps {}
export interface EcommOrdersProps extends BaseProps { }
const EcommOrders = (props: any): JSX.Element => {
const EcommOrders = (props: any): ReactNode => {
return <div className="ar-EcommOrders">In Component EcommOrders</div>
}

View File

@@ -1,9 +1,10 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./EcommProducts.component.scss"
interface EcommProductsProps {}
export interface EcommProductsProps extends BaseProps { }
const EcommProducts = (props: any): JSX.Element => {
const EcommProducts = (props: any): ReactNode => {
return <div className="ar-EcommProducts">In Component EcommProducts</div>
}

View File

@@ -1,9 +1,15 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Empty.component.scss"
interface EmptyProps {}
const Empty = (props: any): JSX.Element => {
export interface EmptyProps extends BaseProps { }
/**
* Component to display empty content message, like empty cart or no data available.
*
* @param props
* @returns
*/
const Empty = (props: any): ReactNode => {
return <div className="ar-Empty">In Component Empty</div>
}

View File

@@ -1,8 +1,9 @@
import { Component, ErrorInfo, ReactNode } from "react"
import Icon from "@armco/icon"
import { BaseProps } from "./types"
import "./ErrorBoundary.component.scss"
interface ErrorBoundaryProps {
export interface ErrorBoundaryProps extends BaseProps {
children?: ReactNode
}
@@ -26,7 +27,7 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, State> {
public render() {
if (this.state.hasError) {
return (
<div className="ar-ErrorBoundary h-100 flex-center flex-1">
<div className={`ar-ErrorBoundary h-100 flex-center flex-1${this.props.classes ? " " + this.props.classes : ""}`}>
<div className="ar-ErrorBoundary__container text-center p-5">
<Icon
icon="md/MdSmsFailed"

View File

@@ -1,8 +1,12 @@
import { FacetedFilterProps } from "@armco/types"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./FacetedFilter.component.scss"
const FacetedFilter = (props: FacetedFilterProps): JSX.Element => {
return <div className="ar-FacetedFilter">In Component FacetedFilter</div>
export interface FacetedFilterProps extends BaseProps { }
const FacetedFilter = (props: FacetedFilterProps): ReactNode => {
const { classes } = props
return <div className={`ar-FacetedFilter${classes ? " " + classes : ""}`}>In Component FacetedFilter</div>
}
export default FacetedFilter

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Faq.component.scss"
interface FaqProps {}
export interface FaqProps extends BaseProps { }
const Faq = (props: any): JSX.Element => {
return <div className="ar-Faq">In Component Faq</div>
const Faq = (props: FaqProps): ReactNode => {
const { classes } = props
return <div className={`ar-Faq${classes ? " " + classes : ""}`}>In Component Faq</div>
}
export default Faq

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Features.component.scss"
interface FeaturesProps {}
export interface FeaturesProps extends BaseProps { }
const Features = (props: any): JSX.Element => {
return <div className="ar-Features">In Component Features</div>
const Features = (props: FeaturesProps): ReactNode => {
const { classes } = props
return <div className={`ar-Features${classes ? " " + classes : ""}`}>In Component Features</div>
}
export default Features

View File

@@ -1,12 +1,14 @@
import { useState } from "react"
import { ReactNode, useState } from "react"
import {
BasicFilterConfig,
BasicFilterType,
FilterConfig,
FilterState,
FiltersProps,
PillProps,
FunctionType,
} from "@armco/types"
import { generateSlices, generateCategories } from "@armco/utils/helper"
import { PillProps } from "./Pill"
import { BaseProps } from "./types"
import AlphabetFilter from "./AlphabetFilter"
import CategoryFilter from "./CategoryFilter"
import Dropdown from "./Dropdown"
@@ -14,7 +16,16 @@ import Pillbox from "./Pillbox"
import Tags from "./Tags"
import "./Filters.component.scss"
const Filters = (props: FiltersProps): JSX.Element => {
export interface FiltersProps extends BaseProps {
clickHandler: FunctionType
data?: Array<any>
filteredData?: Array<any>
config: FilterConfig
initialFilters?: FilterState
onFilterChange: Function
}
const Filters = (props: FiltersProps): ReactNode => {
const {
config,
clickHandler,
@@ -61,8 +72,8 @@ const Filters = (props: FiltersProps): JSX.Element => {
} else if (filterType === "categories") {
const catFilter:
| {
[key: string]: Array<BasicFilterConfig>
}
[key: string]: Array<BasicFilterConfig>
}
| undefined =
filters &&
(filters[filterType] as {
@@ -168,8 +179,8 @@ const Filters = (props: FiltersProps): JSX.Element => {
currentCategoryFilters={
filters && filters.categories
? (filters.categories as {
[key: string]: Array<BasicFilterConfig>
})
[key: string]: Array<BasicFilterConfig>
})
: {}
}
/>

View File

@@ -1,19 +1,21 @@
import { ReactNode } from "react"
import { useEffect } from "react"
import { useNavigate } from "react-router-dom"
import { FunctionType } from "@armco/types"
import { useTheme } from "@armco/utils/hooks"
import { isMobile as checkMobile } from "@armco/utils/helper"
import NAVIGATOR from "@armco/configs/navigator"
import Icon from "@armco/icon"
import {
ArAnimations,
ArLoginProviders,
ArPopoverSlots,
ArTabType,
ArThemes,
FlexToolsProps,
TabBarProps,
TabProps,
} from "@armco/types"
import { useTheme } from "@armco/utils/hooks"
import { isMobile as checkMobile } from "@armco/utils/helper"
import NAVIGATOR from "@armco/configs/navigator"
import Icon from "@armco/icon"
} from "./enums"
import { BaseProps } from "./types"
import { TabBarProps } from "./TabBar"
import { TabProps } from "./Tab"
import AppAndToolsSelector from "./AppAndToolsSelector"
import Popover from "./Popover"
import TabBar from "./TabBar"
@@ -27,8 +29,16 @@ const userOptions = [
const isMobile = checkMobile()
const FlexTools = (props: FlexToolsProps): JSX.Element => {
const { isLanding, route, hideAppLogo, onLogout } = props
export interface FlexToolsProps extends BaseProps {
isLanding?: boolean
route?: string
hideAppLogo?: boolean
onLogout?: FunctionType
}
const FlexTools = (props: FlexToolsProps): ReactNode => {
const { classes, isLanding, route, hideAppLogo, onLogout } = props
const { theme } = useTheme()
const navigate = useNavigate()
@@ -91,9 +101,8 @@ const FlexTools = (props: FlexToolsProps): JSX.Element => {
)
return (
<div
className={`ar-FlexTools h-100 w-100 ${
hideAppLogo ? "flex-v-center justify-content-end" : "flex-center"
}`}
className={`ar-FlexTools h-100 w-100 ${classes ? " " + classes : ""} ${hideAppLogo ? "flex-v-center justify-content-end" : "flex-center"
}`}
>
{!isMobile ? (
<>
@@ -103,9 +112,8 @@ const FlexTools = (props: FlexToolsProps): JSX.Element => {
</>
) : (
<div
className={`w-100${
hideAppLogo ? " d-flex justify-content-end" : " row"
}`}
className={`w-100${hideAppLogo ? " d-flex justify-content-end" : " row"
}`}
>
{!hideAppLogo && (
<div className="col flex-center" onClick={() => navigate("/")}>
@@ -117,9 +125,8 @@ const FlexTools = (props: FlexToolsProps): JSX.Element => {
</div>
)}
<div
className={`ar-FlexTools__app-selector flex-center${
hideAppLogo ? "" : " col"
}`}
className={`ar-FlexTools__app-selector flex-center${hideAppLogo ? "" : " col"
}`}
>
{appSelector}
</div>

View File

@@ -1,13 +1,20 @@
import { ArThemes, FooterProps } from "@armco/types"
import { ReactNode } from "react"
import { FunctionType } from "@armco/types"
import { useSlotted, useTheme } from "@armco/utils/hooks"
import { isMobile as checkMobile } from "@armco/utils/helper"
import Icon from "@armco/icon"
import { ArThemes } from "./enums"
import { BaseProps } from "./types"
import FlexTools from "./FlexTools"
import "./Footer.component.scss"
const isMobile = checkMobile()
const Footer = ({ onThemeToggle }: FooterProps): JSX.Element => {
export interface FooterProps extends BaseProps {
onThemeToggle?: FunctionType
}
const Footer = ({ onThemeToggle }: FooterProps): ReactNode => {
const { theme, setTheme } = useTheme()
useSlotted("Footer")

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Form.component.scss"
interface FormProps {}
export interface FormProps extends BaseProps { }
const Form = (props: any): JSX.Element => {
return <div className="ar-Form">In Component Form</div>
const Form = (props: FormProps): ReactNode => {
const { classes } = props
return <div className={`ar-Form${classes ? " " + classes : ""}`}>In Component Form</div>
}
export default Form

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Gallery.component.scss"
interface GalleryProps {}
export interface GalleryProps extends BaseProps { }
const Gallery = (props: any): JSX.Element => {
return <div className="ar-Gallery">In Component Gallery</div>
const Gallery = (props: GalleryProps): ReactNode => {
const { classes } = props
return <div className={`ar-Gallery${classes ? " " + classes : ""}`}>In Component Gallery</div>
}
export default Gallery

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Graph.component.scss"
interface GraphProps {}
export interface GraphProps extends BaseProps { }
const Graph = (props: any): JSX.Element => {
return <div className="ar-Graph">In Component Graph</div>
const Graph = (props: GraphProps): ReactNode => {
const { classes } = props
return <div className={`ar-Graph${classes ? " " + classes : ""}`}>In Component Graph</div>
}
export default Graph

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./GraphTiles.component.scss"
interface GraphTilesProps {}
export interface GraphTilesProps extends BaseProps { }
const GraphTiles = (props: any): JSX.Element => {
return <div className="ar-GraphTiles">In Component GraphTiles</div>
const GraphTiles = (props: GraphTilesProps): ReactNode => {
const { classes } = props
return <div className={`ar-GraphTiles${classes ? " " + classes : ""}`}>In Component GraphTiles</div>
}
export default GraphTiles

View File

@@ -1,22 +1,43 @@
import { Children } from "react"
import { ArHeaderSlots, HeaderProps } from "@armco/types"
import { Children, ReactNode } from "react"
import { useSlotted } from "@armco/utils/hooks"
import { ArHeaderSlots } from "./enums"
import { BaseProps } from "./types"
import "./Header.component.scss"
const Header = (props: HeaderProps): JSX.Element => {
export interface HeaderProps extends BaseProps {
isFluid?: boolean
isSticky?: boolean
children?: ReactNode
order?: Array<ArHeaderSlots>
}
const Header = (props: HeaderProps): ReactNode => {
const { classes, isFluid, children, order } = props
const childItems: { [key: string]: JSX.Element } = {}
const shuffledItems: Array<JSX.Element> = []
const childItems: Record<string, ReactNode> = {}
const shuffledItems: ReactNode[] = []
useSlotted("Header")
children &&
Children.forEach(children, (child: JSX.Element | null) => {
if (child?.props?.slot) {
childItems[child.props.slot as keyof object] = child
if (children) {
Children.forEach(children, (child) => {
if (
typeof child === "object" &&
child !== null &&
"props" in child &&
child.props &&
typeof child.props === "object" &&
child.props !== null &&
Object.prototype.hasOwnProperty.call(child.props, "slot")
) {
childItems[String((child.props as { slot?: string | number }).slot)] = child
}
})
}
if (order) {
order.forEach((slot) => shuffledItems.push(childItems[slot]))
order.forEach((slot) => {
if (childItems[slot]) {
shuffledItems.push(childItems[slot])
}
})
}
return (
<header className={`ar-Header w-100${classes ? " " + classes : ""}`}>

View File

@@ -1,9 +1,13 @@
import { ArButtonVariants, ArThemes, HeroProps } from "@armco/types"
import Button from "./Button"
import { ReactNode } from "react"
import { useSlotted } from "@armco/utils/hooks"
import { ArButtonVariants, ArThemes } from "./enums"
import { BaseProps } from "./types"
import Button from "./Button"
import "./Hero.component.scss"
const Hero = (props: HeroProps): JSX.Element => {
export interface HeroProps extends BaseProps { }
const Hero = (props: HeroProps): ReactNode => {
const { classes, theme } = props
useSlotted("Hero")

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./HowItWorks.component.scss"
interface HowItWorksProps {}
export interface HowItWorksProps extends BaseProps { }
const HowItWorks = (props: any): JSX.Element => {
return <div className="ar-HowItWorks">In Component HowItWorks</div>
const HowItWorks = (props: HowItWorksProps): ReactNode => {
const { classes } = props
return <div className={`ar-HowItWorks${classes ? " " + classes : ""}`}>In Component HowItWorks</div>
}
export default HowItWorks

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./HttpCode.component.scss"
interface HttpCodeProps {}
export interface HttpCodeProps extends BaseProps { }
const HttpCode = (props: any): JSX.Element => {
return <div className="ar-HttpCode">In Component HttpCode</div>
const HttpCode = (props: HttpCodeProps): ReactNode => {
const { classes } = props
return <div className={`ar-HttpCode${classes ? " " + classes : ""}`}>In Component HttpCode</div>
}
export default HttpCode

View File

@@ -1,5 +1,5 @@
import { CSSProperties, ForwardedRef, forwardRef } from "react"
import { ImageProps } from "@armco/types"
import { CSSProperties, ForwardedRef, forwardRef, ReactNode } from "react"
import { BaseProps } from "./types"
import "./Image.component.scss"
const getDomainFromUrl = (url: string) => {
@@ -16,8 +16,29 @@ const determineCrossOrigin = (url: string) => {
return "anonymous"
}
export interface ImageProps extends BaseProps {
image: string
alt?: string
title?: string
fill?: boolean
preserveAspectRatio?: boolean
flipHorizontal?: boolean
flipVertical?: boolean
rotateBy?: number
opacity?: number
brightness?: number
contrast?: number
saturate?: number
scale?: number
blur?: number
grayscale?: number
sepia?: number
isBackground?: boolean
customBgZIndex?: number
}
const Image = forwardRef(
(props: ImageProps, ref: ForwardedRef<HTMLImageElement>): JSX.Element => {
(props: ImageProps, ref: ForwardedRef<HTMLImageElement>): ReactNode => {
const {
alt,
blur,

View File

@@ -1,5 +1,5 @@
import { useEffect, useState } from "react"
import { InlineMenuProps } from "@armco/types"
import { ReactNode, Ref, useEffect, useState } from "react"
import { BaseProps } from "./types"
import List from "./List"
import "./InlineMenu.component.scss"
@@ -10,7 +10,14 @@ const dummyData = {
Suspend: {},
}
const InlineMenu = (props: InlineMenuProps): JSX.Element => {
export interface InlineMenuProps extends BaseProps {
data: { [key: string]: any }
top?: number
left?: number
ref?: Ref<HTMLDivElement>
}
const InlineMenu = (props: InlineMenuProps): ReactNode => {
const { classes, data, demo, ref, top, left, theme } = props
const [displayed, show] = useState<boolean>()
@@ -22,9 +29,8 @@ const InlineMenu = (props: InlineMenuProps): JSX.Element => {
const finalData = data || (demo && dummyData)
return (
<div
className={`ar-InlineMenu${classes ? " " + classes : ""}${
displayed ? " show px-1 py-2" : ""
}`}
className={`ar-InlineMenu${classes ? " " + classes : ""}${displayed ? " show px-1 py-2" : ""
}`}
style={{ top, left }}
ref={ref}
>

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./InstaPhotos.component.scss"
interface InstaPhotosProps {}
export interface InstaPhotosProps extends BaseProps { }
const InstaPhotos = (props: any): JSX.Element => {
return <div className="ar-InstaPhotos">In Component InstaPhotos</div>
const InstaPhotos = (props: InstaPhotosProps): ReactNode => {
const { classes } = props
return <div className={`ar-InstaPhotos${classes ? " " + classes : ""}`}>In Component InstaPhotos</div>
}
export default InstaPhotos

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Integrations.component.scss"
interface IntegrationsProps {}
export interface IntegrationsProps extends BaseProps { }
const Integrations = (props: any): JSX.Element => {
return <div className="ar-Integrations">In Component Integrations</div>
const Integrations = (props: IntegrationsProps): ReactNode => {
const { classes } = props
return <div className={`ar-Integrations${classes ? " " + classes : ""}`}>In Component Integrations</div>
}
export default Integrations

View File

@@ -1,7 +1,13 @@
import { LabelProps } from "@armco/types"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Label.component.scss"
const Label = (props: LabelProps): JSX.Element => {
export interface LabelProps extends BaseProps {
htmlFor?: string
label: string
}
const Label = (props: LabelProps): ReactNode => {
const { htmlFor, label, style, classes } = props
return (
<label

View File

@@ -1,7 +1,15 @@
import { LabelValueProps, ArLabelValueVariants } from "@armco/types"
import { ReactNode } from "react"
import { ArLabelValueVariants } from "./enums"
import { BaseProps } from "./types"
import "./LabelValue.component.scss"
const LabelValue = (props: LabelValueProps): JSX.Element => {
export interface LabelValueProps extends BaseProps {
label?: string
value?: string
variant?: ArLabelValueVariants
}
const LabelValue = (props: LabelValueProps): ReactNode => {
const { classes, label, value, variant, demo } = props
const useLabel = label ? label : demo ? "First Name" : ""
const useValue = value !== undefined ? value : demo ? "SRK" : ""
@@ -16,15 +24,13 @@ const LabelValue = (props: LabelValueProps): JSX.Element => {
return (
<div
className={`ar-LabelValue d-inline-flex border-radius l2 overflow-hidden${
isLeftLabel ? " flex-v-center" : " flex-column"
}${isBoxed ? " p-2 border" : ""} mb-2${classes ? " " + classes : ""}`}
className={`ar-LabelValue d-inline-flex border-radius l2 overflow-hidden${isLeftLabel ? " flex-v-center" : " flex-column"
}${isBoxed ? " p-2 border" : ""} mb-2${classes ? " " + classes : ""}`}
>
{useLabel && (
<span
className={`ar-LabelValue__label fw-bold d-inline-block${
isLeftLabel ? " me-3" : " mb-2"
}`}
className={`ar-LabelValue__label fw-bold d-inline-block${isLeftLabel ? " me-3" : " mb-2"
}`}
>
{useLabel}
</span>

View File

@@ -1,14 +1,32 @@
import { CSSProperties, Children, cloneElement } from "react"
import { CSSProperties, Children, cloneElement, ReactNode } from "react"
import { useSlotted } from "@armco/utils/hooks"
import { WebPageLayout } from "@armco/configs/constants"
import {
ArComponentLevels,
ArLayoutSlots,
ArWebPageLayout,
LayoutGeneratorProps,
} from "@armco/types"
import { useSlotted } from "@armco/utils/hooks"
import { WebPageLayout } from "@armco/configs/constants"
} from "./enums"
import { BaseProps } from "./types"
import "./LayoutGenerator.component.scss"
export interface LayoutGeneratorProps extends BaseProps {
children?: ReactNode
cardSize?: string
demoChildCount?: number
drawerLevel?: ArComponentLevels
gridSize?: string
hasHeader?: boolean
hasFooter?: boolean
hasDrawer?: boolean
hasSidepanel?: boolean
isFooterFixed?: boolean
selectable?: boolean
sidepanelLevel?: ArComponentLevels
variant?: ArWebPageLayout
[key: string]: any
}
const getDummies = (count: number) => {
return Array(count)
.fill(null)
@@ -16,35 +34,45 @@ const getDummies = (count: number) => {
}
const cloneAndStyleElement = (
element: JSX.Element | null,
element: ReactNode | null,
slot: ArLayoutSlots,
children?: Array<JSX.Element>,
children?: Array<ReactNode>,
style?: CSSProperties,
demo?: boolean,
) => {
if (element) {
if (
element &&
typeof element === "object" &&
element !== null &&
"props" in element &&
(element as any).props &&
typeof (element as any).type === "string"
) {
children?.splice(children.indexOf(element), 1)
return cloneElement(element, {
className: demo
? `border border-radius l2 m-05 p-1 ${element.props.className || ""}${
slot === ArLayoutSlots.HEADER || slot === ArLayoutSlots.FOOTER
? " mih-2"
: ""
}${
slot === ArLayoutSlots.DRAWER || slot === ArLayoutSlots.SIDEPANEL
? " miw-2"
: ""
}`
: element.props.className,
style,
slot,
})
const elProps = (element as { props: any }).props
const newProps: any = {}
if ('className' in elProps) {
newProps.className = demo
? `border border-radius l2 m-05 p-1 ${elProps.className || ""}${slot === ArLayoutSlots.HEADER || slot === ArLayoutSlots.FOOTER
? " mih-2"
: ""
}${slot === ArLayoutSlots.DRAWER || slot === ArLayoutSlots.SIDEPANEL
? " miw-2"
: ""
}`
: elProps.className
}
if ('style' in elProps) {
newProps.style = style
}
newProps.slot = slot
return cloneElement(element as React.ReactElement, newProps)
}
return null
return element
}
const getSlots = (args: {
children?: Array<JSX.Element>
children?: Array<ReactNode>
demo?: boolean
drawerLevel?: ArComponentLevels
hasDrawer?: boolean
@@ -63,35 +91,44 @@ const getSlots = (args: {
hasSidepanel,
// sidepanelLevel,
} = args
const slots: { [key: string]: JSX.Element | null } = {
const slots: Record<string, ReactNode | null> = {
header: null,
footer: null,
drawer: null,
sidepanel: null,
}
Children.forEach(children, (child) => {
child?.props?.slot && (slots[child.props.slot] = child)
if (
typeof child === "object" &&
child !== null &&
"props" in child &&
(child as any).props &&
Object.prototype.hasOwnProperty.call((child as any).props, "slot")
) {
const slotKey = String((child as { props: any }).props.slot)
slots[slotKey] = child
}
})
if (!slots.header && hasHeader) {
slots.header = (children as Array<JSX.Element>)[0]
slots.header = (children as Array<ReactNode>)[0]
}
if (!slots.footer && hasFooter) {
slots.footer = (children as Array<JSX.Element>)[
(children as Array<JSX.Element>).length - 1
slots.footer = (children as Array<ReactNode>)[
(children as Array<ReactNode>).length - 1
]
}
// TODO: wrong child item calculated currently, good for phase 1, change in phase 2 when
// drawer and sidepanel can be at a higher level like header and footer
if (!slots.drawer && hasDrawer) {
slots.drawer = (children as Array<JSX.Element>)[1]
slots.drawer = (children as Array<ReactNode>)[1]
}
if (!slots.sidepanel && hasSidepanel) {
slots.sidepanel = (children as Array<JSX.Element>)[
(children as Array<JSX.Element>).length - 2
slots.sidepanel = (children as Array<ReactNode>)[
(children as Array<ReactNode>).length - 2
]
}
@@ -252,35 +289,45 @@ const LayoutGenerator = ({
childStyle = {}
}
return (
if (
child &&
cloneElement(child, {
className: demo
? `border ${
header ||
footer ||
(variant !== ArWebPageLayout.FULL &&
variant !== ArWebPageLayout.CAROUSEL)
? "border-radius l2 m-05 p-1"
: ""
} ${child.props.className || ""}`
: child.props.className,
style: childStyle,
})
)
typeof child === "object" &&
child !== null &&
"props" in child &&
(child as any).props &&
typeof (child as any).type === "string"
) {
const elProps = (child as { props: any }).props
const newProps: any = {}
if ('className' in elProps) {
newProps.className = demo
? `border ${header ||
footer ||
(variant !== ArWebPageLayout.FULL &&
variant !== ArWebPageLayout.CAROUSEL)
? "border-radius l2 m-05 p-1"
: ""
} ${elProps.className || ""}`
: elProps.className
}
if ('style' in elProps) {
newProps.style = childStyle
}
return cloneElement(child as React.ReactElement, newProps)
}
return child
})
return (
<div
className={`ar-LayoutGenerator d-grid${selectable ? "" : " h-100 w-100"}${
hasContainerGrid ? " header-main-footer-layout" : ""
}${demo ? " bg" : ""}${classes ? " " + classes : ""}`}
className={`ar-LayoutGenerator d-grid${selectable ? "" : " h-100 w-100"}${hasContainerGrid ? " header-main-footer-layout" : ""
}${demo ? " bg" : ""}${classes ? " " + classes : ""}`}
style={
hasContainerGrid
? { gridTemplateRows }
: hasSecondaryGrid
? { gridTemplateColumns }
: style
? { gridTemplateColumns }
: style
}
>
{hasContainerGrid ? (

View File

@@ -1,8 +1,12 @@
import { LearnLinkProps } from "@armco/types"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./LearnLink.component.scss"
const LearnLink = (props: LearnLinkProps): JSX.Element => {
return <div className="ar-LearnLink">In Component LearnLink</div>
export interface LearnLinkProps extends BaseProps { }
const LearnLink = (props: LearnLinkProps): ReactNode => {
const { classes } = props
return <div className={`ar-LearnLink${classes ? " " + classes : ""}`}>In Component LearnLink</div>
}
export default LearnLink

View File

@@ -1,8 +1,26 @@
import { MouseEventHandler, ReactNode } from "react"
import { useNavigate } from "react-router-dom"
import { LinkProps } from "@armco/types"
import { BaseProps } from "./types"
import "./Link.component.scss"
const Link = (props: LinkProps): JSX.Element => {
interface LinkBaseProps extends BaseProps {
to: string
onClick?: MouseEventHandler
openInNew?: boolean
preemptNavigation?: boolean
}
interface LinkLabelProps extends LinkBaseProps {
label: string
}
interface LinkChildrenProps extends LinkBaseProps {
children: ReactNode
}
export type LinkProps =
| (LinkLabelProps & Partial<LinkChildrenProps>)
| (Partial<LinkLabelProps> & LinkChildrenProps)
const Link = (props: LinkProps): ReactNode => {
const {
classes,
label,

View File

@@ -1,6 +1,9 @@
import { ReactNode } from "react"
import { useEffect, useState } from "react"
import { v4 as uuid } from "uuid"
import { ArListStyles, ListItemContent, ListProps } from "@armco/types"
import { FunctionType, ListActionItem, ListItemContent } from "@armco/types"
import { BaseProps } from "./types"
import { ArListVariants, ArListStyles } from "./enums"
import ListItem from "./ListItem"
import "./List.component.scss"
@@ -12,7 +15,22 @@ const dummyData = [
{ name: "+ Upload Icon" },
]
const List = (props: ListProps): JSX.Element => {
export interface ListProps extends BaseProps {
actions?: Array<ListActionItem>
data: Array<ListItemContent>
invertBg?: boolean
isRaw?: boolean
isMultiSelect?: boolean
itemClasses?: string
itemRenderer?: FunctionType
itemVariant?: "soft" | "dynamic"
onItemClick?: FunctionType
showCheckBoxes?: boolean
variant?: ArListVariants
}
const List = (props: ListProps): ReactNode => {
const {
actions,
isRaw,
@@ -83,9 +101,8 @@ const List = (props: ListProps): JSX.Element => {
getListItem(item, "" + index),
)
const commonClasses = `ar-List mb-0${invertBg ? " invert-bg" : '"'} ${
classes ? " " + classes : ""
}${isRaw ? " is-raw" : ""}${showCheckBoxes ? " with-check-boxes" : ""}`
const commonClasses = `ar-List mb-0${invertBg ? " invert-bg" : '"'} ${classes ? " " + classes : ""
}${isRaw ? " is-raw" : ""}${showCheckBoxes ? " with-check-boxes" : ""}`
switch (style) {
case ArListStyles.ORDERED as string:

View File

@@ -1,18 +1,40 @@
import { memo, useEffect, useState } from "react"
import {
ArButtonVariants,
ArListVariants,
ArSizes,
ArThemes,
FunctionType,
ListItemProps,
ListActionItem,
ListItemContent,
ObjectType,
} from "@armco/types"
import { search } from "@armco/utils/helper"
import { useTheme } from "@armco/utils/hooks"
import Icon from "@armco/icon"
import {
ArButtonVariants,
ArListVariants,
ArSizes,
ArThemes,
} from "./enums"
import { BaseProps } from "./types"
import Button from "./Button"
export interface ListItemProps extends BaseProps {
actions?: Array<ListActionItem>
index: string
isMultiSelect?: boolean
isRaw?: boolean
item: ListItemContent
items: Array<ListItemContent>
itemClasses?: string
itemRenderer?: FunctionType
itemVariant?: "soft" | "dynamic"
onClick?: FunctionType
selected?: ListItemContent
setItems: FunctionType
setSelected: FunctionType
showCheckBoxes?: boolean
variant?: ArListVariants
}
const ListItem = memo((props: ListItemProps) => {
const {
actions,
@@ -46,19 +68,17 @@ const ListItem = memo((props: ListItemProps) => {
) : (
<li
key={"list-item-" + index}
className={`ar-List__item mb-0 px-1 flex-v-center${
itemClasses ? " " + itemClasses : ""
}${isRaw ? "" : " cursor-pointer"}${
(
className={`ar-List__item mb-0 px-1 flex-v-center${itemClasses ? " " + itemClasses : ""
}${isRaw ? "" : " cursor-pointer"}${(
isMultiSelect
? isSelected
: !Array.isArray(selected) &&
!Array.isArray(item) &&
(selected?.uid || selected?.name || selected?.label) === (uid || name || label)
!Array.isArray(item) &&
(selected?.uid || selected?.name || selected?.label) === (uid || name || label)
)
? " is-selected"
: ""
} ${variant} ${itemVariant}`}
} ${variant} ${itemVariant}`}
onClick={() => {
if (!isRaw) {
setLocalSelected(!isSelected)
@@ -96,8 +116,8 @@ const ListItem = memo((props: ListItemProps) => {
: "io.IoIosRadioButtonOff"
: (item.uid || item.name || item.label) ===
(selected?.uid || selected?.name || selected?.label)
? "io.IoIosRadioButtonOn"
: "io.IoIosRadioButtonOff"
? "io.IoIosRadioButtonOn"
: "io.IoIosRadioButtonOff"
: ""
}
attributes={{
@@ -139,9 +159,8 @@ const ListItem = memo((props: ListItemProps) => {
<div className="ms-auto border-left ps-2">
{actions?.map((actionItem, index) => (
<Icon
key={`list-action-item-${
!Array.isArray(item) ? uid || label || name : ""
}-${index}`}
key={`list-action-item-${!Array.isArray(item) ? uid || label || name : ""
}-${index}`}
icon={actionItem.icon}
attributes={{
colors: {

View File

@@ -1,10 +1,23 @@
import { ArIconSourceTypes, ArLoaderTypes, LoaderProps } from "@armco/types"
import ProgressIndicator from "./ProgressIndicator"
import { ReactNode } from "react"
import Icon from "@armco/icon"
import ProgressIndicator, { ProgressIndicatorProps } from "./ProgressIndicator"
import { BaseProps } from "./types"
import { ArProgress, ArSizes, ArIconSourceTypes, ArLoaderTypes } from "./enums"
import "./Loader.component.scss"
export interface LoaderProps extends BaseProps {
barVariant?: ProgressIndicatorProps["variant"]
type?: ArLoaderTypes
size?: ArSizes
label?: string
icon?: string
progress?: number
rightEndContent?: ReactNode
status?: ArProgress
}
// Add ability to provide custom loader: an icon or image that rotates
const Loader = (props: LoaderProps): JSX.Element => {
const Loader = (props: LoaderProps): ReactNode => {
const {
barVariant,
classes,
@@ -83,16 +96,13 @@ const Loader = (props: LoaderProps): JSX.Element => {
return (
<div
className={`position-absolute ar-Loader top-0 start-0 h-100 w-100${
classes ? " " + classes : ""
}`}
className={`position-absolute ar-Loader top-0 start-0 h-100 w-100${classes ? " " + classes : ""
}`}
>
<div
className={`ar-Loader-content flex-center w-100 h-100${
type ? " " + type : ""
}${size ? " " + size : ""}${
type !== ArLoaderTypes.SHAPES ? " flex-column" : ""
}`}
className={`ar-Loader-content flex-center w-100 h-100${type ? " " + type : ""
}${size ? " " + size : ""}${type !== ArLoaderTypes.SHAPES ? " flex-column" : ""
}`}
>
{loaderContent}
</div>

View File

@@ -1,10 +1,16 @@
import { ArButtonVariants, ArSizes, LoginProviderProps } from "@armco/types"
import { ReactNode } from "react"
import { IAMCLIENT } from "@armco/configs/endpoints"
import { usePanelContent } from "@armco/utils/hooks"
import { BaseProps } from "./types"
import { ArButtonVariants, ArSizes } from "./enums"
import Button from "./Button"
import "./LoginProvider.component.scss"
const LoginProvider = (props: LoginProviderProps): JSX.Element => {
export interface LoginProviderProps extends BaseProps {
url?: string
}
const LoginProvider = (props: LoginProviderProps): ReactNode => {
const { url } = props
const { setPanelContent: setRightPanelContent } = usePanelContent(false)
return (

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./LogoClouds.component.scss"
interface LogoCloudsProps {}
export interface LogoCloudsProps extends BaseProps { }
const LogoClouds = (props: any): JSX.Element => {
return <div className="ar-LogoClouds">In Component LogoClouds</div>
const LogoClouds = (props: LogoCloudsProps): ReactNode => {
const { classes } = props
return <div className={`ar-LogoClouds${classes ? " " + classes : ""}`}>In Component LogoClouds</div>
}
export default LogoClouds

View File

@@ -1,12 +1,31 @@
import { ArPlacement, MainProps } from "@armco/types"
import { ReactNode } from "react"
import { ObjectType } from "@armco/types"
import { usePanelContent } from "@armco/utils/hooks"
import { BaseProps } from "./types"
import { ArPlacement } from "./enums"
import ErrorBoundary from "./ErrorBoundary"
import SidePanel from "./SidePanel"
import Content from "./Content"
import Drawer from "./Drawer"
import "./Main.component.scss"
const Main = (props: MainProps): JSX.Element => {
export interface MainProps extends BaseProps {
contentClasses?: string
drawerContent?: ReactNode | false
drawerTitle?: string
mainContent?: ReactNode | false
hideSidepanelCloseButton?: boolean
rightPanelContent?:
| { name?: string; component?: ReactNode; props?: ObjectType }
| false
leftPanelContent?:
| { name?: string; component?: ReactNode; props?: ObjectType }
| false
rightPanelHeader?: ReactNode
leftPanelHeader?: ReactNode
}
const Main = (props: MainProps): ReactNode => {
const {
classes,
contentClasses,
@@ -23,9 +42,8 @@ const Main = (props: MainProps): JSX.Element => {
return (
<main
className={`ar-Main d-flex flex-grow-1 w-100${
classes ? " " + classes : ""
}`}
className={`ar-Main d-flex flex-grow-1 w-100${classes ? " " + classes : ""
}`}
>
{drawerContent && (
<Drawer
@@ -51,9 +69,8 @@ const Main = (props: MainProps): JSX.Element => {
/>
<ErrorBoundary>
<Content
classes={`flex-center position-relative overflow-auto${
contentClasses ? " " + contentClasses : ""
}`}
classes={`flex-center position-relative overflow-auto${contentClasses ? " " + contentClasses : ""
}`}
>
{mainContent}
</Content>

View File

@@ -1,8 +1,12 @@
import { MaskProps } from "@armco/types"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Mask.component.scss"
const Mask = (props: MaskProps): JSX.Element => {
return <div className="ar-Mask">In Component Mask</div>
export interface MaskProps extends BaseProps { }
const Mask = (props: MaskProps): ReactNode => {
const { classes } = props
return <div className={`ar-Mask${classes ? " " + classes : ""}`}>In Component Mask</div>
}
export default Mask

View File

@@ -1,4 +1,7 @@
import { useState } from "react"
import { ListItemContent } from "@armco/types"
import Icon from "@armco/icon"
import { BaseProps } from "./types"
import {
ArAnimations,
ArButtonVariants,
@@ -7,13 +10,10 @@ import {
ArPopoverTriggers,
ArSizes,
ArThemes,
ListItemContent,
MenuButtonProps,
} from "@armco/types"
import Icon from "@armco/icon"
} from "./enums"
import List from "./List"
import Popover from "./Popover"
import Button from "./Button"
import Button, { ButtonProps } from "./Button"
import "./Button.component.scss"
const demoSplitOptions: Array<ListItemContent> = [
@@ -22,6 +22,14 @@ const demoSplitOptions: Array<ListItemContent> = [
{ name: "Publish" },
]
export interface MenuButtonProps extends BaseProps {
buttonProps?: ButtonProps
splitButtonClasses?: string
splitOptions?: Array<ListItemContent>
splitPopoverVersion?: string
splitTrigger?: ArPopoverTriggers
}
const MenuButton = (props: MenuButtonProps) => {
const {
buttonProps,
@@ -62,8 +70,8 @@ const MenuButton = (props: MenuButtonProps) => {
? "black"
: "white"
: theme === ArThemes.DARK1
? "white"
: "#3232d8"
? "white"
: "#3232d8"
} else {
setColor = "white"
}
@@ -92,16 +100,15 @@ const MenuButton = (props: MenuButtonProps) => {
splitPopoverVersion
? ArPopoverPositions.AUTO
: hasButton
? ArPopoverPositions.BOTTOMLEFT
: ArPopoverPositions.BOTTOMCENTER
? ArPopoverPositions.BOTTOMLEFT
: ArPopoverPositions.BOTTOMCENTER
}
disabled={disabled}
hideMarker
>
<button
className={`ar-Button ar-Button__split px-1${
splitButtonClasses ? " " + splitButtonClasses : ""
}${variant ? " ar-" + variant : ""}${size ? " ar-" + size : ""}`}
className={`ar-Button ar-Button__split px-1${splitButtonClasses ? " " + splitButtonClasses : ""
}${variant ? " ar-" + variant : ""}${size ? " ar-" + size : ""}`}
type="button"
title="Extra Button Options"
slot={ArPopoverSlots.ANCHOR}

View File

@@ -1,10 +1,11 @@
import { ReactNode, useCallback, useEffect, useRef, useState } from "react"
import { ArButtonVariants, ArSizes, ModalProps, ObjectType } from "@armco/types"
import { FunctionType, ObjectType } from "@armco/types"
import { useSlotted } from "@armco/utils/hooks"
import Icon from "@armco/icon"
import { BaseProps } from "./types"
import { ArButtonVariants, ArSizes } from "./enums"
import Button from "./Button"
import Portal from "./Portal"
import "./Modal.component.scss"
const dummyBody = (
@@ -20,6 +21,25 @@ const dummyBody = (
</div>
)
export interface ModalProps extends BaseProps {
body?: ReactNode
closeHandler?: FunctionType
content?: ReactNode
contentClasses?: string
footer?: ReactNode
header?: ReactNode
hideClose?: boolean
isSticky?: boolean
modalClasses?: string
primaryButtonLabel?: string
primaryHandler?: FunctionType
secondaryButtonLabel?: string
shouldScale?: boolean
shouldFadeIn?: boolean
show?: boolean
}
const Modal = (props: ModalProps): ReactNode => {
const {
body,
@@ -76,10 +96,10 @@ const Modal = (props: ModalProps): ReactNode => {
}
}
}
;(modalRoot.current as HTMLElement).addEventListener(
"keydown",
escCallback,
)
; (modalRoot.current as HTMLElement).addEventListener(
"keydown",
escCallback,
)
}
}, 10)
}, [modalRoot, closeModal, isSticky])
@@ -98,15 +118,13 @@ const Modal = (props: ModalProps): ReactNode => {
return show ? (
<Portal
classes={`position-fixed top-0 left-0 w-100 h-100 modal-container ${
isDisplayed ? "z-2000" : "invisible"
}${classes ? " " + classes : ""}`}
classes={`position-fixed top-0 left-0 w-100 h-100 modal-container ${isDisplayed ? "z-2000" : "invisible"
}${classes ? " " + classes : ""}`}
demo={demo}
>
<div
className={`ar-Modal w-100 h-100${
onBlurCloseAttempted ? " stubborn-effect" : ""
}${modalClasses ? " " + modalClasses : ""}`}
className={`ar-Modal w-100 h-100${onBlurCloseAttempted ? " stubborn-effect" : ""
}${modalClasses ? " " + modalClasses : ""}`}
ref={modalRoot}
tabIndex={-1} // Needed for escape to work
onClick={() => {
@@ -121,11 +139,9 @@ const Modal = (props: ModalProps): ReactNode => {
<div className="ar-Modal__backdrop w-100 h-100 flex-center">
<div
ref={contentRef}
className={`ar-Modal__floating-box d-flex position-relative h-100 overflow-hidden${
shouldScale ? " should-scale" : ""
}${shouldFadeIn ? " should-fade-in" : ""}${
scaleUp ? " scale-up" : ""
}${fadeIn ? " fade-in" : ""}`}
className={`ar-Modal__floating-box d-flex position-relative h-100 overflow-hidden${shouldScale ? " should-scale" : ""
}${shouldFadeIn ? " should-fade-in" : ""}${scaleUp ? " scale-up" : ""
}${fadeIn ? " fade-in" : ""}`}
tabIndex={-1}
onClick={(e) => e.stopPropagation()}
>
@@ -143,9 +159,8 @@ const Modal = (props: ModalProps): ReactNode => {
content
) : (
<div
className={`ar-Modal__content border d-flex flex-1 flex-column overflow-auto${
contentClasses ? " " + contentClasses : ""
}`}
className={`ar-Modal__content border d-flex flex-1 flex-column overflow-auto${contentClasses ? " " + contentClasses : ""
}`}
>
{header ? (
typeof header === "string" ? (

View File

@@ -1,10 +1,12 @@
import React from "react"
import { ReactNode } from "react"
import { BaseProps } from "./types"
import "./Newsletter.component.scss"
interface NewsletterProps {}
export interface NewsletterProps extends BaseProps { }
const Newsletter = (props: any): JSX.Element => {
return <div className="ar-Newsletter">In Component Newsletter</div>
const Newsletter = (props: NewsletterProps): ReactNode => {
const { classes } = props
return <div className={`ar-Newsletter${classes ? " " + classes : ""}`}>In Component Newsletter</div>
}
export default Newsletter

View File

@@ -1,8 +1,12 @@
import { NotificationProps } from "@armco/types"
import { ReactNode } from "react"
import type { BaseProps } from "./types"
import "./Notification.component.scss"
const Notification = (props: NotificationProps): JSX.Element => {
return <div className="ar-Notification">In Component Notification</div>
export interface NotificationProps extends BaseProps { }
const Notification = (props: NotificationProps): ReactNode => {
const { classes } = props
return <div className={`ar-Notification${classes ? " " + classes : ""}`}>In Component Notification</div>
}
export default Notification

View File

@@ -1,3 +0,0 @@
.ar-Notifications {
}

View File

@@ -1,10 +0,0 @@
import React from "react"
import "./Notifications.component.scss"
interface NotificationsProps {}
const Notifications = (props: any): JSX.Element => {
return <div className="ar-Notifications">In Component Notifications</div>
}
export default Notifications

Some files were not shown because too many files have changed in this diff Show More