Stabilised basic functionalities after structured design recovery
Some checks failed
armco-org/Layout/pipeline/head There was a failure building this commit
Some checks failed
armco-org/Layout/pipeline/head There was a failure building this commit
This commit is contained in:
8
package-lock.json
generated
8
package-lock.json
generated
@@ -10,7 +10,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@armco/icon": "^0.0.13",
|
||||
"@armco/shared-components": "^0.0.60",
|
||||
"@armco/shared-components": "^0.0.61",
|
||||
"@armco/utils": "^0.0.31",
|
||||
"bootstrap": "^5.3.8",
|
||||
"react": ">16.8.0",
|
||||
@@ -77,9 +77,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@armco/shared-components": {
|
||||
"version": "0.0.60",
|
||||
"resolved": "https://registry.npmjs.org/@armco/shared-components/-/shared-components-0.0.60.tgz",
|
||||
"integrity": "sha512-Jr8sSrIq+YV3LVsPBrh8YZfTbINf7DHNl4kCSeKx/zueXPimINNz8n6Nd8yk++cp+bAjbhuZUX0hG2QLr8dSQA==",
|
||||
"version": "0.0.61",
|
||||
"resolved": "https://registry.npmjs.org/@armco/shared-components/-/shared-components-0.0.61.tgz",
|
||||
"integrity": "sha512-Nuu5XL0kRwg2C82IiZOSPCnLUqborcyNKP4gulERGic28kduYeBZDSF6oYBKvNAkeGms77mxNGox+0SKJcyeTg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@armco/configs": "^0.0.15",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@armco/icon": "^0.0.13",
|
||||
"@armco/shared-components": "^0.0.60",
|
||||
"@armco/shared-components": "^0.0.61",
|
||||
"@armco/utils": "^0.0.31",
|
||||
"bootstrap": "^5.3.8",
|
||||
"react": ">16.8.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.ar-BuilderLayout.hide-controls {
|
||||
> .ar-Layout__canvas > .ar-Layout__grid-tools {
|
||||
.ar-BuilderLayout {
|
||||
&.hide-controls > .ar-Layout__canvas > .ar-Layout__grid-tools {
|
||||
grid-template: "grid" auto/auto;
|
||||
}
|
||||
.ar-Layout__help-panel {
|
||||
|
||||
@@ -19,10 +19,9 @@ const BuilderLayout: FC<BuilderLayoutProps> = (props) => {
|
||||
isChild,
|
||||
mode,
|
||||
slotDropHandler,
|
||||
onSlotSelect,
|
||||
slotRenderer,
|
||||
} = props
|
||||
const { layoutService, controlsEnabled } = useLayoutContext()
|
||||
const { layoutService, eventsService, controlsEnabled } = useLayoutContext()
|
||||
|
||||
// From runtime: displayMode undefined or 'grid' => treat as grid layout
|
||||
const isGridDisplay = !displayMode || displayMode === "grid"
|
||||
@@ -50,7 +49,7 @@ const BuilderLayout: FC<BuilderLayoutProps> = (props) => {
|
||||
layoutMode: mode,
|
||||
mode: ArSlotViewMode.BUILD as const,
|
||||
dropHandler: slotDropHandler,
|
||||
onSlotSelect,
|
||||
onClick: eventsService.selectSlot,
|
||||
slotRenderer,
|
||||
}
|
||||
return slotRenderer ? (
|
||||
|
||||
@@ -19,11 +19,11 @@ const BuilderLayoutContainer: FC<BuilderLayoutContainerProps> = ({ children, cla
|
||||
if (controlPanelRef.current) {
|
||||
controlPanelRef.current.style.bottom = containerRect.bottom + "px"
|
||||
controlPanelRef.current.style.left = containerRect.left + "px"
|
||||
controlPanelRef.current.style.width = containerRect.width + "px"
|
||||
}
|
||||
if (helpRef.current) {
|
||||
helpRef.current.style.top = window.innerHeight - containerRect.top + "px"
|
||||
helpRef.current.style.left = containerRect.left + "px"
|
||||
helpRef.current.style.width = containerRect.width + "px"
|
||||
}
|
||||
setTimeout(() => {
|
||||
const helpRect = helpRef.current?.getBoundingClientRect()
|
||||
|
||||
@@ -16,8 +16,9 @@ const BuilderSlot = (props: BuilderSlotProps): JSX.Element => {
|
||||
onClick,
|
||||
...rest
|
||||
} = props
|
||||
const { controlsEnabled, selectionOnlyModeEnabled, eventsService } = useLayoutContext()
|
||||
const { controlsEnabled, selectionOnlyModeEnabled } = useLayoutContext()
|
||||
const [selected, setSelected] = useState<boolean>()
|
||||
const [hovered, setHovered] = useState<boolean>(false)
|
||||
const { mode = ArSlotViewMode.BUILD, slotDescriptor } = props
|
||||
const slotRef = useRef<HTMLDivElement>(null)
|
||||
const { slot, props: slotProps } = slotDescriptor
|
||||
@@ -50,11 +51,13 @@ const BuilderSlot = (props: BuilderSlotProps): JSX.Element => {
|
||||
setSelected(!selected)
|
||||
onClick && onClick(slotDescriptor)
|
||||
}}
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
ref={slotRef}
|
||||
{...slotRest}
|
||||
>
|
||||
{content}
|
||||
{controlsEnabled && !selectionOnlyModeEnabled && (
|
||||
{controlsEnabled && !selectionOnlyModeEnabled && hovered && (
|
||||
<SlotTools {...rest} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -114,7 +114,7 @@ const LayoutControlPanel = forwardRef<HTMLDivElement, LayoutControlPanelProps>((
|
||||
key={"layout-control-panel"}
|
||||
>
|
||||
{actionButton(theme, actions[0][0], actions[0][1], actions[0][2], actions[0][3])}
|
||||
{layoutService.slots && (
|
||||
{controlsEnabled && <>{layoutService.slots && (
|
||||
<>
|
||||
<span className="border-right mx-2" />
|
||||
{actions.slice(1, 4).map((e, idx) =>
|
||||
@@ -122,12 +122,13 @@ const LayoutControlPanel = forwardRef<HTMLDivElement, LayoutControlPanelProps>((
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<span className="border-right mx-2" />
|
||||
{actions.slice(4, 10).map((e, idx) => actionButton(theme, e[0], e[1], e[2], e[3], e[4], e[5]))}
|
||||
<span className="border-right mx-2" />
|
||||
{actions.slice(10, 12).map((e, idx) => actionButton(theme, e[0], e[1], e[2], e[3], e[4], e[5]))}
|
||||
<span className="border-right mx-2" />
|
||||
{actions.slice(12).map((e, idx) => actionButton(theme, e[0], e[1], e[2], e[3], e[4], e[5], e[6]))}
|
||||
<span className="border-right mx-2" />
|
||||
{actions.slice(4, 10).map((e, idx) => actionButton(theme, e[0], e[1], e[2], e[3], e[4], e[5]))}
|
||||
<span className="border-right mx-2" />
|
||||
{actions.slice(10, 12).map((e, idx) => actionButton(theme, e[0], e[1], e[2], e[3], e[4], e[5]))}
|
||||
<span className="border-right mx-2" />
|
||||
{actions.slice(12).map((e, idx) => actionButton(theme, e[0], e[1], e[2], e[3], e[4], e[5], e[6]))
|
||||
}</>}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -7,6 +7,7 @@ import Icon from "@armco/icon"
|
||||
|
||||
type LayoutHelpProps = {
|
||||
panelsDisplayed?: boolean
|
||||
classes?: string
|
||||
}
|
||||
|
||||
const keyBindings = [
|
||||
@@ -35,7 +36,7 @@ const helpPoints = [
|
||||
]
|
||||
|
||||
const LayoutHelp = forwardRef<HTMLDivElement, LayoutHelpProps>(
|
||||
({ panelsDisplayed }, ref) => {
|
||||
({ panelsDisplayed, classes }, ref) => {
|
||||
const { theme } = useTheme()
|
||||
const cmdIcon = useMemo(
|
||||
() => (
|
||||
@@ -46,13 +47,14 @@ const LayoutHelp = forwardRef<HTMLDivElement, LayoutHelpProps>(
|
||||
),
|
||||
[],
|
||||
)
|
||||
const fillColor = theme === ArThemes.DARK1 ? "black" : "white"
|
||||
return (
|
||||
<div
|
||||
className={`ar-Layout__help-panel position-fixed overflow-hidden d-flex px-2 justify-content-between py-1${panelsDisplayed ? " show" : ""
|
||||
}`}
|
||||
}${classes ? " " + classes : ""}`}
|
||||
ref={ref}
|
||||
>
|
||||
<span className="small fw-bold" style={{ color: theme === ArThemes.DARK1 ? "black" : "white" }}>
|
||||
<span className="small fw-bold" style={{ color: fillColor }}>
|
||||
Undo: Ctrl/Cmd + z, Redo: Ctrl/Cmd + y
|
||||
</span>
|
||||
<div>
|
||||
@@ -60,7 +62,7 @@ const LayoutHelp = forwardRef<HTMLDivElement, LayoutHelpProps>(
|
||||
<Icon
|
||||
icon="fa.FaKeyboard"
|
||||
slot={ArPopoverSlots.ANCHOR}
|
||||
attributes={{ colors: { fillColor: "white" }, classes: "me-3" }}
|
||||
attributes={{ colors: { fillColor }, classes: "me-3" }}
|
||||
/>
|
||||
<span slot={ArPopoverSlots.POPOVER} className="z-2">
|
||||
{keyBindings.map((kb) => (
|
||||
@@ -77,7 +79,7 @@ const LayoutHelp = forwardRef<HTMLDivElement, LayoutHelpProps>(
|
||||
<Icon
|
||||
icon="md.MdInfoOutline"
|
||||
slot={ArPopoverSlots.ANCHOR}
|
||||
attributes={{ colors: { fillColor: theme === ArThemes.DARK1 ? "black" : "white" } }}
|
||||
attributes={{ colors: { fillColor } }}
|
||||
/>
|
||||
<span
|
||||
className="ar-Layout__help-panel__help-content small z-2"
|
||||
|
||||
@@ -7,15 +7,18 @@
|
||||
}
|
||||
}
|
||||
.ar-Slot {
|
||||
.build {
|
||||
&.build {
|
||||
&:hover {
|
||||
border: 1px dashed #7d31f0 !important;
|
||||
border: 1px solid #7d31f0 !important;
|
||||
.ar-SlotTools {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
border: 1px solid #86cff1 !important;
|
||||
&:hover {
|
||||
border: 1px solid #7d31f0 !important;
|
||||
}
|
||||
}
|
||||
&.active {
|
||||
outline: 4px solid #2e9cfd !important;
|
||||
@@ -29,24 +32,29 @@
|
||||
background-color: #55bdeda9;
|
||||
}
|
||||
}
|
||||
.ar-SlotTools {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.ar-SlotTools {
|
||||
display: none;
|
||||
}
|
||||
.row-controller .ar-Slot__overlay-btn {
|
||||
&.row-controller .ar-Slot__overlay-btn {
|
||||
height: calc((100% - 16px) / 3);
|
||||
&.delete {
|
||||
height: 1rem;
|
||||
}
|
||||
}
|
||||
.col-controller .ar-Slot__overlay-btn {
|
||||
&.col-controller .ar-Slot__overlay-btn {
|
||||
width: calc((100% - 16px) / 3);
|
||||
&.delete {
|
||||
width: 1rem;
|
||||
}
|
||||
}
|
||||
.row-controller,
|
||||
.col-controller {
|
||||
&.row-controller,
|
||||
&.col-controller {
|
||||
&:hover {
|
||||
.ar-SlotTools {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
.ar-Slot__overlay-btn {
|
||||
&.slot:hover {
|
||||
background-color: #55bdeda9;
|
||||
|
||||
37
src/Test.tsx
37
src/Test.tsx
@@ -1,8 +1,10 @@
|
||||
import { useState } from "react"
|
||||
import ReactDOM from "react-dom/client"
|
||||
import { DndProvider } from "react-dnd"
|
||||
import { HTML5Backend } from "react-dnd-html5-backend"
|
||||
import { TouchBackend } from "react-dnd-touch-backend"
|
||||
import { isMobile as checkMobile } from "@armco/utils/helper"
|
||||
import { ArProvider } from "@armco/utils"
|
||||
import Layout from "./Layout"
|
||||
import "./test.scss"
|
||||
|
||||
@@ -11,4 +13,37 @@ const backend = isMobile ? TouchBackend : HTML5Backend
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement)
|
||||
|
||||
root.render(<div className="flex-center h-100 w-100 container"><DndProvider backend={backend}><Layout /></DndProvider></div>)
|
||||
function formatGridTemplate(templateString: string) {
|
||||
// 1. Normalize all whitespace in the string
|
||||
let formatted = templateString.trim().replace(/\s+/g, ' ');
|
||||
|
||||
// 2. Replace the '/' separator with a newline and indentation
|
||||
formatted = formatted.replace(' / ', '\n/ ');
|
||||
|
||||
// 3. Replace spaces that separate distinct *rows* or *column groups* with newlines
|
||||
// This looks for a space that is immediately followed by a starting quote or the '/' character
|
||||
formatted = formatted.replace(/\s+(?=["/])/g, '\n');
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
const LayoutWrapper = () => {
|
||||
const [gridTemplate, setGridTemplate] = useState<string>("")
|
||||
return <div className="d-flex h-100 w-100">
|
||||
<div className="flex-center w-50 p-3">
|
||||
<Layout onLayoutChange={(gridTemplate: string) => setGridTemplate(gridTemplate)} acceptTextOnClick />
|
||||
</div>
|
||||
<div className="bg-dark w-50 text-white p-4">
|
||||
<strong className="mb-4 d-inline-block fs-4">GRID TEMPLATE</strong>
|
||||
{gridTemplate && <pre className="custom-scrollbar p-1">{formatGridTemplate(gridTemplate)}</pre>}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
root.render(<div className="flex-center h-100 w-100">
|
||||
<ArProvider>
|
||||
<DndProvider backend={backend}>
|
||||
<LayoutWrapper />
|
||||
</DndProvider>
|
||||
</ArProvider>
|
||||
</div>)
|
||||
|
||||
@@ -19,7 +19,9 @@ export default defineConfig({
|
||||
build: {
|
||||
outDir: "build",
|
||||
lib: {
|
||||
entry: glob.sync(resolve(__dirname, "src/**/!(*.d).{ts,tsx}")),
|
||||
entry: glob
|
||||
.sync(resolve(__dirname, "src/**/!(*.d).{ts,tsx}"))
|
||||
.filter((p) => !p.endsWith("Test.tsx")),
|
||||
},
|
||||
rollupOptions: {
|
||||
treeshake: true,
|
||||
|
||||
Reference in New Issue
Block a user