Fixed compile errors, added publish scripts

This commit is contained in:
2024-10-05 23:09:35 +05:30
parent eb12f43379
commit a49a6fee65
19 changed files with 1860 additions and 1872 deletions

View File

@@ -4,26 +4,9 @@
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
rm -rf build
# Quality check
npx tsc
# Generate Styles (with unneeded js)
# vite build --config vite-css.config.ts
vite build
# Generated source bundle
# tsc -p tsconfig.cjs.build.json
# tsc -p tsconfig.es.build.json
# Cleanup unneeded js
# rm -f build/*.js
# # Copy image files
# find src/static -type f \( -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" -o -name "*.gif" -o -name "*.svg" \) -exec cp {} build/cjs/static/ \;
# find src/static -type f \( -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" -o -name "*.gif" -o -name "*.svg" \) -exec cp {} build/es/static/ \;
# Run Post processors: Update style imports in .js files, create component modules
node "$SCRIPT_DIR/post-processor.js" build/cjs
node "$SCRIPT_DIR/post-processor.js" build/es

View File

@@ -5,7 +5,7 @@ import { fileURLToPath } from "url"
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const exclusions = ["enums.js", "navigator.js", "v4.js", "index.js"]
const exclusions = ["enums.js", "v4.js", "index.js"]
async function generateModule(fileName) {
if (!exclusions.includes(fileName)) {

34
package-lock.json generated
View File

@@ -1,15 +1,15 @@
{
"name": "@armco/utils",
"version": "0.0.7",
"version": "0.0.18",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@armco/utils",
"version": "0.0.7",
"version": "0.0.18",
"license": "ISC",
"dependencies": {
"@armco/configs": "^0.0.3",
"@armco/configs": "^0.0.7",
"@armco/types": "^0.0.9",
"d3": "^7.9.0",
"uuid": "^10.0.0"
@@ -25,6 +25,7 @@
"typescript": "^5.0.2",
"vite": "^5.4.6",
"vite-plugin-dts": "^4.2.1",
"vite-plugin-externalize-deps": "^0.8.0",
"vitest": "^2.1.1"
},
"peerDependencies": {
@@ -46,15 +47,21 @@
}
},
"node_modules/@armco/configs": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@armco/configs/-/configs-0.0.3.tgz",
"integrity": "sha512-1gdJmMIkAVttA8D2gZmKlVEs5mEnSkr94BjZfyQa0/A6oQgVt2EMEgJmCUkHy2YzitFm8a8ZtOfM3cvdKTQoWg==",
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/@armco/configs/-/configs-0.0.7.tgz",
"integrity": "sha512-iniTmpR0kaOmRXAKw7cmXMyVnd1M+gOG/gNEOvmNAxRt8AuvW8WBra96o6oHnk0LFPgZhzmKSHvWzO1ADErxZQ==",
"license": "ISC",
"dependencies": {
"@armco/types": "^0.0.9",
"@armco/types": "^0.0.10",
"uuid": "^10.0.0"
}
},
"node_modules/@armco/configs/node_modules/@armco/types": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/@armco/types/-/types-0.0.10.tgz",
"integrity": "sha512-PKmehb5PsX6o6b3yaItCyDJxYy5nyXBduONnWv6slQwBMareFquGUcrCORPQhvnVLprCTs5aIZyPerZdjVuuxg==",
"license": "MIT"
},
"node_modules/@armco/types": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/@armco/types/-/types-0.0.9.tgz",
@@ -4070,6 +4077,19 @@
}
}
},
"node_modules/vite-plugin-externalize-deps": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/vite-plugin-externalize-deps/-/vite-plugin-externalize-deps-0.8.0.tgz",
"integrity": "sha512-MdC8kRNQ1ZjhUicU2HcqGVhL0UUFqv83Zp1JZdHjE82PoPR8wsSWZ3axpot7B6img3sW6g8shYJikE0CKA0chA==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/voracious"
},
"peerDependencies": {
"vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0"
}
},
"node_modules/vitest": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.1.tgz",

View File

@@ -1,12 +1,13 @@
{
"name": "@armco/utils",
"version": "0.0.7",
"version": "0.0.18",
"type": "module",
"scripts": {
"build": "./build-tools/build.sh",
"format": "prettier --write .",
"lint": "eslint .",
"publish:sh": "./publish.sh"
"publish:sh": "./publish.sh",
"publish:local": "./publish-local.sh"
},
"devDependencies": {
"@types/d3": "^7.4.3",
@@ -19,10 +20,11 @@
"typescript": "^5.0.2",
"vite": "^5.4.6",
"vite-plugin-dts": "^4.2.1",
"vite-plugin-externalize-deps": "^0.8.0",
"vitest": "^2.1.1"
},
"dependencies": {
"@armco/configs": "^0.0.3",
"@armco/configs": "^0.0.7",
"@armco/types": "^0.0.9",
"d3": "^7.9.0",
"uuid": "^10.0.0"

16
publish-local.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/sh
semver=${1:-patch}
set -e
npm run build
cp package.json build/
sed -i '' -E 's/"build"/"*"/' build/package.json
sed -i '' 's#"build/cjs/index.js"#"cjs/index.js"#' build/package.json
sed -i '' 's#"build/es/index.js"#"es/index.js"#' build/package.json
sed -i '' 's#"build/types/index.d.ts"#"types/index.d.ts"#' build/package.json
cd build
npm pack --pack-destination ~/__Projects__/Common

View File

@@ -2,7 +2,15 @@
semver=${1:-patch}
npm run build
set -e
npm --no-git-tag-version version ${semver}
npm run build
cp package.json build/
sed -i '' -E 's/"build"/"*"/' build/package.json
sed -i '' 's#"build/cjs/index.js"#"cjs/index.js"#' build/package.json
sed -i '' 's#"build/es/index.js"#"es/index.js"#' build/package.json
sed -i '' 's#"build/types/index.d.ts"#"types/index.d.ts"#' build/package.json
cd build
npm publish --access public --loglevel verbose

View File

@@ -6,7 +6,7 @@ import {
TreeListData,
RecusionConditionTypes,
} from "@armco/types"
import RecursionHelper from "./recursionHelper"
import { injectIds } from "./recursionHelper"
const years = Array.from({ length: 60 }, (_, i) => 1964 + i)
const countries = ["IN", "US", "RU", "CN", "UK", "JP", "FR", "IT", "SP"]
@@ -29,100 +29,96 @@ const dummyProgressiveChartData: ThreeDChartDataArrayFormat = countries.flatMap(
},
)
class Adapter {
static adaptToTreeFromComponentConfig(data: any): Array<TreeListData> {
const returnTreeList: Array<TreeListData> = []
Object.keys(data).forEach((key) => {
const groupConfig = data[key as keyof any]
const components = groupConfig.components
components.sort((c1: ComponentDescription, c2: ComponentDescription) =>
(c1.name as any) > (c2.name as any) ? 1 : -1,
)
const obj: TreeListData = {
label: groupConfig.label,
children: [],
data: { ...groupConfig },
}
components.forEach((item: any) => {
const treeItem: TreeListData = {
label: typeof item === "string" ? item : item.name,
data: {
component: typeof item === "string" ? item : item.name,
hierarchy: key,
},
}
const children: Array<any> = []
treeItem.children = children
if (item.variants && Object.keys(item.variants.length > 0)) {
Object.keys(item.variants).forEach((variantKey) => {
const variants = item.variants[variantKey]
treeItem.children &&
treeItem.children.push({
label: variantKey,
data: { name: typeof item === "string" ? item : item.name },
children: variants.map((v: string) => ({
label: v,
data: {
component: typeof item === "string" ? item : item.name,
props: { [variantKey]: v },
hierarchy: key,
},
})),
})
})
}
obj.children && obj.children.push(treeItem)
})
returnTreeList.push(obj)
})
RecursionHelper.injectIds({
data: returnTreeList,
condition: { type: RecusionConditionTypes.KEY_EXISTS, key: "label" },
iterateOn: "children",
})
return returnTreeList
}
static adaptToProgressiveChart(
inputData: ProgressiveChartData,
demo?: boolean,
): ThreeDChartDataObjectFormat {
if (demo && !inputData) {
inputData = dummyProgressiveChartData
export function adaptToTreeFromComponentConfig(data: any): Array<TreeListData> {
const returnTreeList: Array<TreeListData> = []
Object.keys(data).forEach((key) => {
const groupConfig = data[key as keyof any]
const components = groupConfig.components
components.sort((c1: ComponentDescription, c2: ComponentDescription) =>
(c1.name as any) > (c2.name as any) ? 1 : -1,
)
const obj: TreeListData = {
label: groupConfig.label,
children: [],
data: { ...groupConfig },
}
let unsortedData: ThreeDChartDataObjectFormat = {}
// Transform the data into the desired format
if (Array.isArray(inputData)) {
inputData.forEach(([key, xValue, yValue]) => {
if (!unsortedData[key]) {
unsortedData[key] = [[xValue, yValue]]
} else {
unsortedData[key].push([xValue, yValue])
}
})
} else {
unsortedData = inputData
}
// Sort the keys
const keys = Object.keys(unsortedData)
keys.sort((a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a - b
} else {
return a.localeCompare(b)
components.forEach((item: any) => {
const treeItem: TreeListData = {
label: typeof item === "string" ? item : item.name,
data: {
component: typeof item === "string" ? item : item.name,
hierarchy: key,
},
}
const children: Array<any> = []
treeItem.children = children
if (item.variants && Object.keys(item.variants.length > 0)) {
Object.keys(item.variants).forEach((variantKey) => {
const variants = item.variants[variantKey]
treeItem.children &&
treeItem.children.push({
label: variantKey,
data: { name: typeof item === "string" ? item : item.name },
children: variants.map((v: string) => ({
label: v,
data: {
component: typeof item === "string" ? item : item.name,
props: { [variantKey]: v },
hierarchy: key,
},
})),
})
})
}
obj.children && obj.children.push(treeItem)
})
// Create a new object with the sorted keys
let sortedData: ThreeDChartDataObjectFormat = {}
keys.forEach((key) => {
sortedData[key] = unsortedData[key]
})
return sortedData
}
returnTreeList.push(obj)
})
injectIds({
data: returnTreeList,
condition: { type: RecusionConditionTypes.KEY_EXISTS, key: "label" },
iterateOn: "children",
})
return returnTreeList
}
export default Adapter
export function adaptToProgressiveChart(
inputData: ProgressiveChartData,
demo?: boolean,
): ThreeDChartDataObjectFormat {
if (demo && !inputData) {
inputData = dummyProgressiveChartData
}
let unsortedData: ThreeDChartDataObjectFormat = {}
// Transform the data into the desired format
if (Array.isArray(inputData)) {
inputData.forEach(([key, xValue, yValue]) => {
if (!unsortedData[key]) {
unsortedData[key] = [[xValue, yValue]]
} else {
unsortedData[key].push([xValue, yValue])
}
})
} else {
unsortedData = inputData
}
// Sort the keys
const keys = Object.keys(unsortedData)
keys.sort((a, b) => {
if (typeof a === "number" && typeof b === "number") {
return a - b
} else {
return a.localeCompare(b)
}
})
// Create a new object with the sorted keys
let sortedData: ThreeDChartDataObjectFormat = {}
keys.forEach((key) => {
sortedData[key] = unsortedData[key]
})
return sortedData
}

View File

@@ -1,6 +1,6 @@
import { createContext } from "react"
import { ArContextType, ArThemes, FunctionType } from "@armco/types"
import Helper from "./helper"
import { isMobile } from "./helper"
export const SlotterContext = createContext<{
slotted: Array<string>
@@ -9,7 +9,7 @@ export const SlotterContext = createContext<{
export const ArContext = createContext<ArContextType>({
theme: ArThemes.DARK1,
drawerState: { collapsed: Helper.isMobile() },
drawerState: { collapsed: isMobile() },
notify: () => {},
setDrawerState: () => {},
setLeftPanelContent: () => {},

View File

@@ -1,6 +1,6 @@
import { CalendarDate, Event, ArDateFormats } from "@armco/types"
import { MONTH_INDEX } from "@armco/configs"
import Helper from "./helper"
import { MONTH_INDEX } from "@armco/configs/constants"
import { pad } from "./helper"
export interface CalendarOptions {
/**
@@ -402,8 +402,8 @@ class Calendar {
separator: string = "/",
format: string = "DDMMYYYY",
) {
const day = Helper.pad(date.day, separator)
const month = Helper.pad(date.month + 1, separator)
const day = pad(date.day, separator)
const month = pad(date.month + 1, separator)
const year = date.year
switch (format) {

View File

@@ -1,5 +1,4 @@
import { FunctionType } from "@armco/types"
import { ArDateMasks } from "@armco/types"
import { ArDateMasks, FunctionType } from "@armco/types"
const token =
/d{1,4}|D{3,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|W{1,2}|[LlopSZN]|"[^"]*"|'[^']*'/g
@@ -334,3 +333,5 @@ export const formatTimezone = (date: Date) => {
?.replace(timezoneClip, "")
.replace(/GMT\+0000/g, "UTC")
}
export { dateFormat as DateFormatter }

View File

@@ -6,451 +6,447 @@ import {
ObjectType,
Position,
} from "@armco/types"
import Helper from "./helper"
import { getStylesFromClass } from "./helper"
class DomHelper {
static style = window.getComputedStyle(document.documentElement)
static fontSize = parseFloat(DomHelper.style.fontSize)
static markerSize = 7
const style = window.getComputedStyle(document.documentElement)
const fontSize = parseFloat(style.fontSize)
const markerSize = 7
static outerWidth(el: HTMLElement) {
let width = el.offsetWidth
const style = getComputedStyle(el)
export function outerWidth(el: HTMLElement) {
let width = el.offsetWidth
const style = getComputedStyle(el)
width += parseInt(style.marginLeft) + parseInt(style.marginRight)
return width
}
width += parseInt(style.marginLeft) + parseInt(style.marginRight)
return width
}
static translate(
position: number,
metric: "px" | "%",
axis: "horizontal" | "vertical",
) {
const positionPercent = position === 0 ? position : position + metric
const positionCss =
axis === "horizontal" ? [positionPercent, 0, 0] : [0, positionPercent, 0]
const transitionProp = "translate3d"
export function translate(
position: number,
metric: "px" | "%",
axis: "horizontal" | "vertical",
) {
const positionPercent = position === 0 ? position : position + metric
const positionCss =
axis === "horizontal" ? [positionPercent, 0, 0] : [0, positionPercent, 0]
const transitionProp = "translate3d"
const translatedPosition = "(" + positionCss.join(",") + ")"
const translatedPosition = "(" + positionCss.join(",") + ")"
return transitionProp + translatedPosition
}
return transitionProp + translatedPosition
}
static hexToHsl(color: string, returnRaw?: boolean) {
const [r, g, b] = DomHelper.hexToRgb(color)
return DomHelper.rgbToHsl(r, g, b, returnRaw)
}
export function hexToHsl(color: string, returnRaw?: boolean) {
const [r, g, b] = hexToRgb(color)
return rgbToHsl(r, g, b, returnRaw)
}
static hexToRgb(color: string) {
const r = parseInt(color.substring(1, 3), 16) // Grab the hex representation of red (chars 1-2) and convert to decimal (base 10).
const g = parseInt(color.substring(3, 5), 16)
const b = parseInt(color.substring(5, 7), 16)
return [r, g, b]
}
export function hexToRgb(color: string) {
const r = parseInt(color.substring(1, 3), 16) // Grab the hex representation of red (chars 1-2) and convert to decimal (base 10).
const g = parseInt(color.substring(3, 5), 16)
const b = parseInt(color.substring(5, 7), 16)
return [r, g, b]
}
/**
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h, s, and l in the set [0, 1].
*
* @param Number r The red color value
* @param Number g The green color value
* @param Number b The blue color value
* @return Array The HSL representation
*/
static rgbToHsl(r: number, g: number, b: number, returnRaw?: boolean) {
r /= 255
g /= 255
b /= 255
/**
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h, s, and l in the set [0, 1].
*
* @param Number r The red color value
* @param Number g The green color value
* @param Number b The blue color value
* @return Array The HSL representation
*/
export function rgbToHsl(r: number, g: number, b: number, returnRaw?: boolean) {
r /= 255
g /= 255
b /= 255
const max = Math.max(r, g, b),
min = Math.min(r, g, b)
let h,
s,
l = (max + min) / 2
const max = Math.max(r, g, b),
min = Math.min(r, g, b)
let h,
s,
l = (max + min) / 2
if (max === min) {
h = s = 0 // achromatic
} else {
const d = max - min
s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
if (max === min) {
h = s = 0 // achromatic
} else {
const d = max - min
s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0)
break
case g:
h = (b - r) / d + 2
break
case b:
h = (r - g) / d + 4
break
}
// @ts-ignore
h /= 6
}
const colorInHSL = "hsl(" + h + ", " + s + "%, " + l + "%)"
return returnRaw ? [h, s, l] : colorInHSL
}
static hslToRgb(h: number, s: number, l: number) {
let r, g, b
let hue2rgb
if (s === 0) {
r = g = b = l // achromatic
} else {
hue2rgb = (p: number, q: number, t: number) => {
if (t < 0) t += 1
if (t > 1) t -= 1
if (t < 1 / 6) return p + (q - p) * 6 * t
if (t < 1 / 2) return q
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
return p
}
const q = l < 0.5 ? l * (1 + s) : l + s - l * s
const p = 2 * l - q
r = hue2rgb && hue2rgb(p, q, h + 1 / 3)
g = hue2rgb && hue2rgb(p, q, h)
b = hue2rgb && hue2rgb(p, q, h - 1 / 3)
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0)
break
case g:
h = (b - r) / d + 2
break
case b:
h = (r - g) / d + 4
break
}
return [r * 255, g * 255, b * 255]
// @ts-ignore
h /= 6
}
const colorInHSL = "hsl(" + h + ", " + s + "%, " + l + "%)"
return returnRaw ? [h, s, l] : colorInHSL
}
export function hslToRgb(h: number, s: number, l: number) {
let r, g, b
let hue2rgb
if (s === 0) {
r = g = b = l // achromatic
} else {
hue2rgb = (p: number, q: number, t: number) => {
if (t < 0) t += 1
if (t > 1) t -= 1
if (t < 1 / 6) return p + (q - p) * 6 * t
if (t < 1 / 2) return q
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
return p
}
const q = l < 0.5 ? l * (1 + s) : l + s - l * s
const p = 2 * l - q
r = hue2rgb && hue2rgb(p, q, h + 1 / 3)
g = hue2rgb && hue2rgb(p, q, h)
b = hue2rgb && hue2rgb(p, q, h - 1 / 3)
}
static rgbToHex(r: number, g: number, b: number) {
function componentToHex(c: number) {
var hex = c.toString(16)
return hex.length === 1 ? "0" + hex : hex
}
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b)
return [r * 255, g * 255, b * 255]
}
export function rgbToHex(r: number, g: number, b: number) {
function componentToHex(c: number) {
var hex = c.toString(16)
return hex.length === 1 ? "0" + hex : hex
}
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b)
}
export function hslToHex(h: number, s: number, l: number) {
const [r, g, b] = hslToRgb(h, s, l)
return rgbToHex(Math.round(r), Math.round(g), Math.round(b))
}
export function implementSvgStyles(
svg: SVGSVGElement,
svgProps?: IconProps["attributes"],
flags?: Array<boolean>,
) {
const { size, classes, colors, strokeWidth } = svgProps || {}
const { fillColor, strokeColor } = colors || {}
const [skipPathColorFill] = flags || []
let styles = null
if (classes) {
styles = getStylesFromClass(classes)
styles = Object.entries(styles || {})
.map(([property, value]) => `${property}: ${value}`)
.join("; ")
}
svg.setAttribute("height", size || "1rem")
svg.setAttribute("width", size || "1rem")
svg.setAttribute("class", classes || "")
svg.setAttribute("style", styles || "")
svg.setAttribute("stroke", strokeColor || "black")
strokeWidth
? svg.setAttribute("stroke-width", strokeWidth)
: strokeColor && svg.setAttribute("stroke-width", "1")
let path: SVGPathElement | NodeListOf<SVGPathElement> =
svg.querySelectorAll("path")
if (path.length === 1 && !skipPathColorFill) {
path = path[0]
// Override stroke and color of "path" node inside SVG at below line.
path &&
strokeColor &&
!!path.getAttribute("stroke") &&
path.setAttribute("stroke", strokeColor)
path &&
strokeWidth &&
!!path.getAttribute("stroke-width") &&
path.setAttribute("stroke-width", strokeWidth)
path &&
fillColor &&
!!path.getAttribute("fill") &&
path.setAttribute("fill", fillColor)
}
svg.style.color = fillColor || "black"
return svg
}
/**
* Gets the list 'position' relative to a current index
* @param index
*/
export function getPosition(index: number, props: CarouselProps): number {
if (props.infiniteLoop) {
// index has to be added by 1 because of the first cloned slide
++index
}
static hslToHex(h: number, s: number, l: number) {
const [r, g, b] = DomHelper.hslToRgb(h, s, l)
return DomHelper.rgbToHex(Math.round(r), Math.round(g), Math.round(b))
if (index === 0) {
return 0
}
static implementSvgStyles(
svg: SVGSVGElement,
svgProps?: IconProps["attributes"],
flags?: Array<boolean>,
) {
const { size, classes, colors, strokeWidth } = svgProps || {}
const { fillColor, strokeColor } = colors || {}
const [skipPathColorFill] = flags || []
let styles = null
if (classes) {
styles = Helper.getStylesFromClass(classes)
styles = Object.entries(styles || {})
.map(([property, value]) => `${property}: ${value}`)
.join("; ")
const childrenLength = Children.count(props.children)
if (props.centerMode && props.axis === "horizontal") {
let currentPosition = -index * props.centerSlidePercentage
const lastPosition = childrenLength - 1
if (index && (index !== lastPosition || props.infiniteLoop)) {
currentPosition += (100 - props.centerSlidePercentage) / 2
} else if (index === lastPosition) {
currentPosition += 100 - props.centerSlidePercentage
}
svg.setAttribute("height", size || "1rem")
svg.setAttribute("width", size || "1rem")
svg.setAttribute("class", classes || "")
svg.setAttribute("style", styles || "")
svg.setAttribute("stroke", strokeColor || "black")
strokeWidth
? svg.setAttribute("stroke-width", strokeWidth)
: strokeColor && svg.setAttribute("stroke-width", "1")
let path: SVGPathElement | NodeListOf<SVGPathElement> =
svg.querySelectorAll("path")
if (path.length === 1 && !skipPathColorFill) {
path = path[0]
// Override stroke and color of "path" node inside SVG at below line.
path &&
strokeColor &&
!!path.getAttribute("stroke") &&
path.setAttribute("stroke", strokeColor)
path &&
strokeWidth &&
!!path.getAttribute("stroke-width") &&
path.setAttribute("stroke-width", strokeWidth)
path &&
fillColor &&
!!path.getAttribute("fill") &&
path.setAttribute("fill", fillColor)
}
svg.style.color = fillColor || "black"
return svg
return currentPosition
}
/**
* Gets the list 'position' relative to a current index
* @param index
*/
static getPosition(index: number, props: CarouselProps): number {
if (props.infiniteLoop) {
// index has to be added by 1 because of the first cloned slide
++index
return -index * 100
}
/**
* Sets the 'position' transform for sliding animations
* @param position
* @param forceReflow
*/
export function setPosition(
position: number,
axis: "horizontal" | "vertical",
): React.CSSProperties {
const style = {}
;[
"WebkitTransform",
"MozTransform",
"MsTransform",
"OTransform",
"transform",
"msTransform",
].forEach((prop) => {
// @ts-ignore
style[prop] = CSSTranslate(position, "%", axis)
})
return style
}
export function isKeyboardEvent(
e?: React.MouseEvent | React.KeyboardEvent,
): e is React.KeyboardEvent {
return e ? e.hasOwnProperty("key") : false
}
export function getDocumentElement(demo?: boolean) {
// Check if the component is running inside an iframe
if (demo) {
const iframeElement =
document.querySelector<HTMLIFrameElement>(".ar-Editor__frame")
if (iframeElement) {
return iframeElement.contentDocument
}
if (index === 0) {
return 0
}
const childrenLength = Children.count(props.children)
if (props.centerMode && props.axis === "horizontal") {
let currentPosition = -index * props.centerSlidePercentage
const lastPosition = childrenLength - 1
if (index && (index !== lastPosition || props.infiniteLoop)) {
currentPosition += (100 - props.centerSlidePercentage) / 2
} else if (index === lastPosition) {
currentPosition += 100 - props.centerSlidePercentage
}
return currentPosition
}
return -index * 100
}
// Return the parent document element by default
return document
}
/**
* Sets the 'position' transform for sliding animations
* @param position
* @param forceReflow
*/
static setPosition(
position: number,
axis: "horizontal" | "vertical",
): React.CSSProperties {
const style = {}
;[
"WebkitTransform",
"MozTransform",
"MsTransform",
"OTransform",
"transform",
"msTransform",
].forEach((prop) => {
// @ts-ignore
style[prop] = CSSTranslate(position, "%", axis)
})
export function getWindowElement(demo?: boolean) {
// Check if the component is running inside an iframe
if (demo) {
const iframeElement =
document.querySelector<HTMLIFrameElement>(".ar-Editor__frame")
return style
}
static isKeyboardEvent(
e?: React.MouseEvent | React.KeyboardEvent,
): e is React.KeyboardEvent {
return e ? e.hasOwnProperty("key") : false
}
static getDocumentElement(demo?: boolean) {
// Check if the component is running inside an iframe
if (demo) {
const iframeElement =
document.querySelector<HTMLIFrameElement>(".ar-Editor__frame")
if (iframeElement) {
return iframeElement.contentDocument
}
if (iframeElement) {
return iframeElement.contentWindow
}
// Return the parent document element by default
return document
}
// Return the parent document element by default
return window
}
static getWindowElement(demo?: boolean) {
// Check if the component is running inside an iframe
if (demo) {
const iframeElement =
document.querySelector<HTMLIFrameElement>(".ar-Editor__frame")
if (iframeElement) {
return iframeElement.contentWindow
}
}
// Return the parent document element by default
return window
export function shouldUsePosition(
position: ArPopoverPositions,
anchorRect: DOMRect,
popoverRect: DOMRect,
demo?: boolean,
) {
const windowObj = getWindowElement(demo) || window
const exceeds: ObjectType = {
bottom:
anchorRect.top + anchorRect.height + popoverRect.height >
windowObj.innerHeight,
right:
anchorRect.left + anchorRect.width + popoverRect.width >
windowObj.innerWidth,
left: anchorRect.left - popoverRect.width < 0,
top: anchorRect.top - popoverRect.height < 0,
}
static shouldUsePosition(
position: ArPopoverPositions,
anchorRect: DOMRect,
popoverRect: DOMRect,
demo?: boolean,
) {
const windowObj = DomHelper.getWindowElement(demo) || window
const exceeds: ObjectType = {
bottom:
anchorRect.top + anchorRect.height + popoverRect.height >
windowObj.innerHeight,
right:
anchorRect.left + anchorRect.width + popoverRect.width >
windowObj.innerWidth,
left: anchorRect.left - popoverRect.width < 0,
top: anchorRect.top - popoverRect.height < 0,
}
if (exceeds[position]) return false
if (position === "left" || position === "right") {
if (
DomHelper.fontSize > anchorRect.top ||
DomHelper.fontSize > anchorRect.bottom
)
return false
} else {
if (
DomHelper.fontSize > anchorRect.left ||
DomHelper.fontSize > anchorRect.right
)
return false
}
return position
}
static adjustPosition(
position: ArPopoverPositions,
anchorRect: DOMRect,
popoverRect: DOMRect,
hideMarker?: boolean,
topOffset?: number,
) {
const popoverPositions: { [key: string]: Position } = {
[ArPopoverPositions.BOTTOM]: {
top:
anchorRect.top +
anchorRect.height +
(hideMarker ? 0 : DomHelper.markerSize) +
(topOffset || 0),
left: anchorRect.left + (anchorRect.width - popoverRect.width) / 2,
},
[ArPopoverPositions.RIGHT]: {
top: anchorRect.top + (anchorRect.height - popoverRect.height) / 2,
left:
anchorRect.left +
anchorRect.width +
(hideMarker ? 0 : DomHelper.markerSize),
},
[ArPopoverPositions.LEFT]: {
top: anchorRect.top + (anchorRect.height - popoverRect.height) / 2,
left:
anchorRect.left -
popoverRect.width -
(hideMarker ? 0 : DomHelper.markerSize),
},
[ArPopoverPositions.TOP]: {
top:
anchorRect.top -
popoverRect.height -
(hideMarker ? 0 : DomHelper.markerSize) -
(topOffset || 0),
left: anchorRect.left + (anchorRect.width - popoverRect.width) / 2,
},
}
let { left, top } = popoverPositions[position]
if (exceeds[position]) return false
if (position === "left" || position === "right") {
if (
position === ArPopoverPositions.BOTTOM ||
position === ArPopoverPositions.TOP
fontSize > anchorRect.top ||
fontSize > anchorRect.bottom
)
return false
} else {
if (
fontSize > anchorRect.left ||
fontSize > anchorRect.right
)
return false
}
return position
}
export function adjustPosition(
position: ArPopoverPositions,
anchorRect: DOMRect,
popoverRect: DOMRect,
hideMarker?: boolean,
topOffset?: number,
) {
const popoverPositions: { [key: string]: Position } = {
[ArPopoverPositions.BOTTOM]: {
top:
anchorRect.top +
anchorRect.height +
(hideMarker ? 0 : markerSize) +
(topOffset || 0),
left: anchorRect.left + (anchorRect.width - popoverRect.width) / 2,
},
[ArPopoverPositions.RIGHT]: {
top: anchorRect.top + (anchorRect.height - popoverRect.height) / 2,
left:
anchorRect.left +
anchorRect.width +
(hideMarker ? 0 : markerSize),
},
[ArPopoverPositions.LEFT]: {
top: anchorRect.top + (anchorRect.height - popoverRect.height) / 2,
left:
anchorRect.left -
popoverRect.width -
(hideMarker ? 0 : markerSize),
},
[ArPopoverPositions.TOP]: {
top:
anchorRect.top -
popoverRect.height -
(hideMarker ? 0 : markerSize) -
(topOffset || 0),
left: anchorRect.left + (anchorRect.width - popoverRect.width) / 2,
},
}
let { left, top } = popoverPositions[position]
if (
position === ArPopoverPositions.BOTTOM ||
position === ArPopoverPositions.TOP
) {
if ((left as number) < 0) {
left = fontSize
}
if ((left as number) + popoverRect.width > window.innerWidth) {
left = `calc(100% - ${popoverRect.width}px - ${fontSize}px)`
}
} else {
if ((top as number) < 0) {
top = fontSize
}
if ((top as number) + popoverRect.height > window.innerHeight) {
top = `calc(100% - ${popoverRect.height}px - ${fontSize}px)`
}
}
return { left, top }
}
export function getPositionToUse(
anchorRect: DOMRect,
popoverRect: DOMRect,
requestedPosition?: ArPopoverPositions,
demo?: boolean,
) {
if (requestedPosition && requestedPosition !== ArPopoverPositions.AUTO) {
return requestedPosition
}
const positionsPriority = [
ArPopoverPositions.BOTTOM,
ArPopoverPositions.RIGHT,
ArPopoverPositions.LEFT,
ArPopoverPositions.TOP,
]
for (const position of positionsPriority) {
if (
shouldUsePosition(position, anchorRect, popoverRect, demo)
) {
if ((left as number) < 0) {
left = DomHelper.fontSize
}
if ((left as number) + popoverRect.width > window.innerWidth) {
left = `calc(100% - ${popoverRect.width}px - ${DomHelper.fontSize}px)`
}
} else {
if ((top as number) < 0) {
top = DomHelper.fontSize
}
if ((top as number) + popoverRect.height > window.innerHeight) {
top = `calc(100% - ${popoverRect.height}px - ${DomHelper.fontSize}px)`
}
return position
}
return { left, top }
continue
}
static getPositionToUse(
anchorRect: DOMRect,
popoverRect: DOMRect,
requestedPosition?: ArPopoverPositions,
demo?: boolean,
) {
if (requestedPosition && requestedPosition !== ArPopoverPositions.AUTO) {
return requestedPosition
}
const positionsPriority = [
ArPopoverPositions.BOTTOM,
ArPopoverPositions.RIGHT,
ArPopoverPositions.LEFT,
ArPopoverPositions.TOP,
]
return ArPopoverPositions.BOTTOM
}
for (const position of positionsPriority) {
if (
DomHelper.shouldUsePosition(position, anchorRect, popoverRect, demo)
) {
return position
export function calculatePopoverPosition(
anchorRect: DOMRect,
popoverRect: DOMRect,
requestedPosition?: ArPopoverPositions,
hideMarker?: boolean,
clickCoordinates?: Array<number> | null,
demo?: boolean,
topOffset?: number,
) {
const windowObj = getWindowElement(demo) || window
anchorRect = clickCoordinates
? {
left: clickCoordinates[0],
x: clickCoordinates[0],
top: clickCoordinates[1],
y: clickCoordinates[1],
height: 0,
width: 0,
right: windowObj.screen.width - clickCoordinates[0],
bottom: windowObj.screen.height - clickCoordinates[1],
toJSON: () => {},
}
continue
}
return ArPopoverPositions.BOTTOM
}
static calculatePopoverPosition(
anchorRect: DOMRect,
popoverRect: DOMRect,
requestedPosition?: ArPopoverPositions,
hideMarker?: boolean,
clickCoordinates?: Array<number> | null,
demo?: boolean,
topOffset?: number,
) {
const windowObj = DomHelper.getWindowElement(demo) || window
anchorRect = clickCoordinates
? {
left: clickCoordinates[0],
x: clickCoordinates[0],
top: clickCoordinates[1],
y: clickCoordinates[1],
height: 0,
width: 0,
right: windowObj.screen.width - clickCoordinates[0],
bottom: windowObj.screen.height - clickCoordinates[1],
toJSON: () => {},
}
: anchorRect
const position = DomHelper.getPositionToUse(
anchorRect,
popoverRect,
requestedPosition,
demo,
)
const { left, top } = DomHelper.adjustPosition(
position,
anchorRect,
popoverRect,
hideMarker,
topOffset,
)
return {
leftTop: {
top: ("" + top).startsWith("calc") ? top : top + "px",
left: ("" + left).startsWith("calc") ? left : left + "px",
},
position,
}
}
static openInNewTab(url: string) {
const win = window.open(url, "_blank")
if (win != null) {
win.focus()
}
}
static download(dataURL: any) {
const anchor = document.createElement("a")
anchor.href = dataURL
anchor.download = "edited-image.png"
document.body.appendChild(anchor)
anchor.click()
document.body.removeChild(anchor)
: anchorRect
const position = getPositionToUse(
anchorRect,
popoverRect,
requestedPosition,
demo,
)
const { left, top } = adjustPosition(
position,
anchorRect,
popoverRect,
hideMarker,
topOffset,
)
return {
leftTop: {
top: ("" + top).startsWith("calc") ? top : top + "px",
left: ("" + left).startsWith("calc") ? left : left + "px",
},
position,
}
}
export default DomHelper
export function openInNewTab(url: string) {
const win = window.open(url, "_blank")
if (win != null) {
win.focus()
}
}
export function download(data: string | Blob, filename?: string) {
const anchor = document.createElement("a")
anchor.href = typeof data === "string" ? data : window.URL.createObjectURL(data)
anchor.download = filename || "edited-image.png"
document.body.appendChild(anchor)
anchor.click()
document.body.removeChild(anchor)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,11 @@
export { dateFormat as DateFormatter } from "./dateformat"
export { default as DomHelper } from "./domHelper"
export { default as Adapter } from "./adapters"
export { default as Helper } from "./helper"
export { default as Network } from "./network"
export { default as Validator } from "./validators"
export { default as GridHelper } from "./gridHelper"
export { default as RecursionHelper } from "./recursionHelper"
export * from "./dateformat"
export * from "./domHelper"
export * from "./adapters"
export * from "./helper"
export * from "./network"
export * from "./validators"
export * from "./gridHelper"
export * from "./recursionHelper"
export * from "./dateHelper"
export * from "./chartGenerators"
export * from "./hooks"

View File

@@ -1,5 +1,5 @@
import { FunctionType, ObjectType } from "@armco/types"
import { API_CONFIG } from "@armco/configs"
import { HOST, STATIC_HOST } from "@armco/configs/endpoints"
interface Options extends RequestInit {
// headers?: {
@@ -36,30 +36,29 @@ class Error {
}
}
export default class Network {
static MAX_ATTEMPTS_LIMIT = 10
const MAX_ATTEMPTS_LIMIT = 10
static async get(url: string, queryParams?: object, options?: Options) {
const urlString = Network.stringifyUrl(url, queryParams)
export async function get(url: string, queryParams?: object, options?: Options) {
const urlString = stringifyUrl(url, queryParams)
options = {
method: "GET",
mode: "cors",
credentials: "include",
...options,
}
return Network.crud(urlString, options)
return crud(urlString, options)
}
static async getStatic(
export async function getStatic(
url: string,
queryParams?: object | null,
options?: Options | null,
) {
let urlString = Network.stringifyUrl(url, queryParams)
let urlString = stringifyUrl(url, queryParams)
const environment = process.env.NODE_ENV || "development"
const host = urlString.startsWith("http")
? ""
: API_CONFIG.STATIC_HOST[environment as keyof object]
: STATIC_HOST[environment as keyof object]
urlString = host ? host + urlString : urlString
options = {
method: "GET",
@@ -67,10 +66,10 @@ export default class Network {
credentials: "include",
...options,
}
return Network.crud(urlString, options)
return crud(urlString, options)
}
static async post(
export async function post(
url: string,
data: object,
queryParams?: object,
@@ -78,7 +77,7 @@ export default class Network {
noStringify?: boolean,
noHeaders?: boolean,
) {
const urlString = Network.stringifyUrl(url, queryParams)
const urlString = stringifyUrl(url, queryParams)
options = {
method: "POST",
// @ts-ignore
@@ -90,20 +89,20 @@ export default class Network {
options &&
(options.headers = { "Content-Type": "application/json" })
// @ts-ignore
return Network.crud(urlString, options)
return crud(urlString, options)
}
static async upload(
export async function upload(
url: string,
file: File,
queryParams?: object,
options?: Options,
) {
let urlString = Network.stringifyUrl(url, queryParams)
let urlString = stringifyUrl(url, queryParams)
const environment = process.env.NODE_ENV || "development"
const host = urlString.startsWith("http")
? ""
: API_CONFIG.STATIC_HOST[environment as keyof object]
: STATIC_HOST[environment as keyof object]
urlString = host ? host + urlString : urlString
const formData = new FormData()
formData.append("file", file)
@@ -114,11 +113,11 @@ export default class Network {
credentials: "include",
...options,
}
return Network.crud(urlString, options)
return crud(urlString, options)
}
static async put(url: string, data: object, queryParams?: object) {
const urlString = Network.stringifyUrl(url, queryParams)
export async function put(url: string, data: object, queryParams?: object) {
const urlString = stringifyUrl(url, queryParams)
const options: Options = {
method: "PUT",
body: JSON.stringify(data),
@@ -128,23 +127,23 @@ export default class Network {
"Content-Type": "application/json",
},
}
return Network.crud(urlString, options)
return crud(urlString, options)
}
static async delete(url: string, queryParams: object) {
const urlString = Network.stringifyUrl(url, queryParams)
export async function deleteRec(url: string, queryParams: object) {
const urlString = stringifyUrl(url, queryParams)
const options = {
method: "DELETE",
noInject: true,
}
return Network.crud(urlString, options)
return crud(urlString, options)
}
static async crud(urlString: string, options: Options) {
export async function crud(urlString: string, options: Options) {
const environment = process.env.NODE_ENV || "development"
const host = urlString.startsWith("http")
? ""
: API_CONFIG.HOST[environment as keyof object]
: HOST[environment as keyof object]
const extras = options?.extras
urlString = host ? host + urlString : urlString
if (!options.headers) {
@@ -183,7 +182,7 @@ export default class Network {
throw new Error(err.error || err.message, status, extras)
}
static stringifyUrl(url: string, queryParams?: any) {
export function stringifyUrl(url: string, queryParams?: any) {
if (!queryParams) {
return url || ""
}
@@ -203,7 +202,7 @@ export default class Network {
: ""
}
static async retry(
export async function retry(
fn: FunctionType,
retryOptions: RetryOptions | undefined = {},
) {
@@ -214,7 +213,7 @@ export default class Network {
onSuccess,
onFailure,
} = retryOptions
maxAttempts = Math.min(maxAttempts, Network.MAX_ATTEMPTS_LIMIT)
maxAttempts = Math.min(maxAttempts, MAX_ATTEMPTS_LIMIT)
let attempts = 0
const attempt = async () => {
@@ -244,4 +243,3 @@ export default class Network {
return attempt()
}
}

View File

@@ -8,7 +8,7 @@ import {
User,
} from "@armco/types"
import { ArContext } from "./contexts"
import Helper from "./helper"
import { isMobile } from "./helper"
export const ArProvider = ({ children }: { children: ReactNode }) => {
const [theme, setTheme] = useState<ArThemes>(ArThemes.DARK1)
@@ -19,7 +19,7 @@ export const ArProvider = ({ children }: { children: ReactNode }) => {
)
const [notification, notify] = useState<AlertProps | undefined>(undefined)
const [drawerState, setDrawerState] = useState<DrawerProps>({
collapsed: Helper.isMobile(),
collapsed: isMobile(),
})
const [leftPanelContent, setLeftPanelContent] = useState<
PanelContent | undefined

View File

@@ -1,66 +1,62 @@
import { v4 as uuid } from "uuid"
import { RecursionArgs, ObjectType, RecusionConditionTypes } from "@armco/types"
class RecursionHelper {
static recur(args: RecursionArgs) {
const { condition, data, isBrute, preop, postop, iterateOn } = args
if (isBrute) {
if (Array.isArray(data)) {
data.forEach((item) => {
RecursionHelper.recur({ ...args, data: item })
})
} else if (typeof data === "object") {
const preopResult = preop && preop(data)
Object.values(data).forEach((item: any) => {
RecursionHelper.recur({ ...args, data: item })
})
return (postop && postop(data)) || preopResult
}
} else {
if (Array.isArray(data)) {
data.forEach((item) => {
RecursionHelper.recur({ ...args, data: item })
})
} else if (
typeof data === "object" &&
(!condition || RecursionHelper.evaluateCondition(data, condition))
) {
const preopResult = preop && preop(data)
if (iterateOn) {
if (data[iterateOn]) {
RecursionHelper.recur({ ...args, data: data[iterateOn] })
}
} else {
Object.values(data).forEach((item) => {
RecursionHelper.recur({ ...args, data: item })
})
export function recur(args: RecursionArgs) {
const { condition, data, isBrute, preop, postop, iterateOn } = args
if (isBrute) {
if (Array.isArray(data)) {
data.forEach((item) => {
recur({ ...args, data: item })
})
} else if (typeof data === "object") {
const preopResult = preop && preop(data)
Object.values(data).forEach((item: any) => {
recur({ ...args, data: item })
})
return (postop && postop(data)) || preopResult
}
} else {
if (Array.isArray(data)) {
data.forEach((item) => {
recur({ ...args, data: item })
})
} else if (
typeof data === "object" &&
(!condition || evaluateCondition(data, condition))
) {
const preopResult = preop && preop(data)
if (iterateOn) {
if (data[iterateOn]) {
recur({ ...args, data: data[iterateOn] })
}
return (postop && postop(data)) || preopResult
} else {
Object.values(data).forEach((item) => {
recur({ ...args, data: item })
})
}
return (postop && postop(data)) || preopResult
}
return null
}
static injectIds(args: RecursionArgs) {
args.postop = (item) => !item.id && (item.id = uuid())
RecursionHelper.recur(args)
}
static evaluateCondition(data: ObjectType, condition: ObjectType): boolean {
if (!data || !condition) {
return false
}
if (condition.type === RecusionConditionTypes.KEY_EXISTS) {
return !!(condition.key && (condition.key as string) in data)
} else if (condition.type === RecusionConditionTypes.KEY_VALUE) {
return !!(
condition.key &&
condition.value &&
data[condition.key as string] === condition.value
)
}
return false
}
return null
}
export default RecursionHelper
export function injectIds(args: RecursionArgs) {
args.postop = (item) => !item.id && (item.id = uuid())
recur(args)
}
export function evaluateCondition(data: ObjectType, condition: ObjectType): boolean {
if (!data || !condition) {
return false
}
if (condition.type === RecusionConditionTypes.KEY_EXISTS) {
return !!(condition.key && (condition.key as string) in data)
} else if (condition.type === RecusionConditionTypes.KEY_VALUE) {
return !!(
condition.key &&
condition.value &&
data[condition.key as string] === condition.value
)
}
return false
}

View File

@@ -1,17 +1,13 @@
import { ObjectType } from "@armco/types"
class Validator {
static validateTask(taskObj: ObjectType) {
return (
taskObj &&
taskObj.name &&
taskObj.client &&
taskObj.target &&
(taskObj.target as ObjectType).endpoint &&
taskObj.schedule &&
(taskObj.schedule as ObjectType).cron
)
}
export function validateTask(taskObj: ObjectType) {
return (
taskObj &&
taskObj.name &&
taskObj.client &&
taskObj.target &&
(taskObj.target as ObjectType).endpoint &&
taskObj.schedule &&
(taskObj.schedule as ObjectType).cron
)
}
export default Validator

View File

@@ -3,10 +3,11 @@ import {glob} from "glob"
import { defineConfig } from "vitest/config"
import react from "@vitejs/plugin-react"
import dts from "vite-plugin-dts"
import { externalizeDeps } from "vite-plugin-externalize-deps"
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), dts({ outDir: "build/types" })],
plugins: [react(), dts({ outDir: "build/types" }), externalizeDeps()],
build: {
outDir: "build",
lib: {
@@ -14,7 +15,6 @@ export default defineConfig({
},
rollupOptions: {
treeshake: true,
external: ["react", "react/jsx-runtime", "react-dom"],
output: [
{
format: "es",