Fixed compile errors, added publish scripts
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
34
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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
16
publish-local.sh
Executable 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
|
||||
10
publish.sh
10
publish.sh
@@ -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
|
||||
|
||||
182
src/adapters.ts
182
src/adapters.ts
@@ -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
|
||||
}
|
||||
|
||||
@@ -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: () => {},
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 }
|
||||
810
src/domHelper.ts
810
src/domHelper.ts
@@ -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)
|
||||
}
|
||||
|
||||
1444
src/gridHelper.ts
1444
src/gridHelper.ts
File diff suppressed because it is too large
Load Diff
978
src/helper.tsx
978
src/helper.tsx
File diff suppressed because it is too large
Load Diff
16
src/index.ts
16
src/index.ts
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user