Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions CONSTANTS_REFACTOR_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Allonsh Constants Refactor Summary

## Overview

This document summarizes the refactoring work done to replace hardcoded values with meaningful constants throughout the Allonsh library.

## Files Created/Modified

### 1. New Constants File: `src/constants.js`

- **Z_INDEX**: Centralized z-index values (GHOST: 999, DRAGGING: 1000, DROPPED: 9999, etc.)
- **DEFAULTS**: Default configuration values (stack spacing, direction)
- **CSS_CLASSES**: Consistent CSS class names
- **CSS_POSITIONS**: Position values (relative, absolute)
- **CSS_CURSORS**: Cursor values (grab, grabbing)
- **OPACITY**: Opacity values (ghost: 0.3, full: 1)
- **EVENTS**: Custom event names
- **FLEX_DIRECTIONS**: Flexbox direction values
- **DISPLAY_MODES**: Display property values
- **POINTER_EVENTS**: Pointer-events values

### 2. Main Library: `src/allonsh.js`

**Replaced hardcoded values with constants:**

#### Z-Index Values:

- `999` → `Z_INDEX.GHOST`
- `1000` → `Z_INDEX.DRAGGING`
- `9999` → `Z_INDEX.DROPPED`

#### Default Values:

- `'horizontal'` → `DEFAULTS.STACK_DIRECTION`
- `5` → `DEFAULTS.STACK_SPACING`

#### CSS Class Names:

- `'restricted'` → `CSS_CLASSES.RESTRICTED`

#### CSS Properties:

- `'relative'` → `CSS_POSITIONS.RELATIVE`
- `'absolute'` → `CSS_POSITIONS.ABSOLUTE`
- `'grab'` → `CSS_CURSORS.GRAB`
- `'grabbing'` → `CSS_CURSORS.GRABBING`
- `'flex'` → `DISPLAY_MODES.FLEX`
- `'row'` → `FLEX_DIRECTIONS.ROW`
- `'column'` → `FLEX_DIRECTIONS.COLUMN`
- `'wrap'` → `FLEX_WRAP`

#### Opacity Values:

- `'0.3'` → `OPACITY.GHOST`
- `'1'` → `OPACITY.FULL`

#### Pointer Events:

- `'none'` → `POINTER_EVENTS.NONE`
- `'auto'` → `POINTER_EVENTS.AUTO`

#### Event Names:

### 3. Demo Script: `demo/js/script.js`

- Imported constants for default values
- Replaced hardcoded `10` with `DEFAULTS.STACK_SPACING_DEMO`

### 4. Test File: `test/allonsh.test.js`

- Imported constants for event names
- Replaced hardcoded event name with `EVENTS.DROP`

### 5. CSS File: `demo/css/styles.css`

- Added comments indicating z-index values could be updated to use CSS custom properties
- Values remain hardcoded for now but are documented for future refactoring

## Benefits Achieved

1. **Maintainability**: All hardcoded values are now centralized in one location
2. **Consistency**: Values are guaranteed to be consistent across the codebase
3. **Self-documenting**: Constants have meaningful names that explain their purpose
4. **Easy Updates**: Changing a value requires updating only the constants file
5. **Type Safety**: Better IDE support and error detection
6. **Code Clarity**: Intent is clearer with named constants instead of magic numbers

## Future Improvements

1. **CSS Custom Properties**: Z-index values in CSS could be moved to CSS custom properties
2. **Theme System**: Constants could be extended to support theme-based values
3. **Configuration**: Constants could be made configurable at runtime
4. **Validation**: Add validation to ensure constant values are within expected ranges

## Impact

- **High Priority**: This was a quick win with massive maintainability improvement
- **Low Risk**: Changes are purely internal refactoring with no API changes
- **High Value**: Makes the codebase significantly easier to maintain and extend
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,27 @@ Initialize Allonsh by importing the module and providing the required options.

```js
import Allonsh from './allonsh.js';
import { CSS_CLASSES, EVENTS } from './constants.js';

// Initialize Allonsh with options
const allonsh = new Allonsh({
draggableSelector: 'allonsh-draggable', // Required: class for draggable elements
dropzoneSelector: 'allonsh-dropzone', // Optional: class for dropzones
draggableSelector: CSS_CLASSES.DRAGGABLE, // Required: class for draggable elements
dropzoneSelector: CSS_CLASSES.DROPZONE, // Optional: class for dropzones
playAreaSelector: 'play-area', // Optional: class for the container area
restrictToDropzones: false, // Optional: restrict dragging to dropzones
enableStacking: true, // Optional: enable stacking inside dropzones
stackDirection: 'horizontal', // Optional: 'horizontal' or 'vertical'
stackSpacing: 8, // Optional: spacing between stacked items (px)
useGhostEffect: true, // Optional: enable ghost effect (shows transparent clone while dragging)
});

// Listen for custom events
document.addEventListener(EVENTS.DRAG_START, (e) => {
// handle drag start
});
document.addEventListener(EVENTS.DROP, (e) => {
// handle drop
});
```

## Documentation
Expand Down
31 changes: 23 additions & 8 deletions demo/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ body {
/* Header */
.demo-header {
position: fixed;
z-index: 10;
z-index: var(
--allonsh-z-index-header,
10
); /* migrated to CSS custom property */
box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.5);
display: flex;
justify-content: space-between;
Expand Down Expand Up @@ -212,7 +215,7 @@ body.night .demo-section__playground {
margin-top: 3rem;
padding: 2rem 0;
font-size: 0.95rem;
opacity: 0.8;
opacity: var(--allonsh-opacity-demo, 0.8);
}

/* Theme Toggle (if applicable) */
Expand All @@ -226,7 +229,10 @@ body.night .demo-section__playground {
padding: 0.6rem;
border-radius: 50%;
cursor: pointer;
z-index: 1000;
z-index: var(
--allonsh-z-index-dragging,
1000
); /* migrated to CSS custom property */
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

Expand Down Expand Up @@ -260,7 +266,7 @@ body.night .demo-section__playground {
justify-content: center;
height: 500px;
background-color: var(--panel-bg);
opacity: 0.8;
opacity: var(--allonsh-opacity-demo, 0.8);
background-image:
linear-gradient(135deg, var(--panel-border) 25%, transparent 25%),
linear-gradient(225deg, var(--panel-border) 25%, transparent 25%),
Expand All @@ -287,7 +293,10 @@ body.night .demo-section__playground {
background-color: var(--bg-color);
padding: 1rem;
left: 1.5rem;
z-index: 5;
z-index: var(
--allonsh-z-index-control-panel,
5
); /* migrated to CSS custom property */
font-size: 1.2rem;
font-weight: 600;
border: 2px solid var(--panel-border);
Expand Down Expand Up @@ -354,7 +363,7 @@ body.night .demo-section__playground {
border: none;
padding: 0.5rem;
cursor: pointer;
z-index: 5;
z-index: var(--allonsh-z-index-freemode-title, 5);
}

.toggle-panel-btn.open {
Expand Down Expand Up @@ -427,7 +436,10 @@ body.night .demo-section__playground {
border-radius: 1rem;
cursor: pointer;
transition: background-color 0.3s;
z-index: 9;
z-index: var(
--allonsh-z-index-theme-toggle,
9
); /* migrated to CSS custom property */
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

Expand All @@ -445,7 +457,10 @@ body.night .demo-section__playground {
position: fixed;
bottom: 1rem;
left: 1rem;
z-index: 9;
z-index: var(
--allonsh-z-index-theme-toggle,
9
); /* migrated to CSS custom property */
transform: translateX(-120%);
transition: transform 0.3s ease;
}
Expand Down
39 changes: 22 additions & 17 deletions demo/js/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Allonsh from '../../src/allonsh.js';
const openPanelBtn = document.getElementById('openPanelBtn');
const closePanelBtn = document.getElementById('closePanelBtn');

import { DEFAULTS, CSS_CLASSES, EVENTS } from '../../src/constants.js';
Copy link

@coderabbitai coderabbitai bot Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix duplicate import and remove unused identifier.

DEFAULTS is imported twice (Lines 6 and 42), triggering a linter error. Also, EVENTS is imported but never used.

Apply this diff:

-import { DEFAULTS, CSS_CLASSES, EVENTS } from '../../src/constants.js';
+import { DEFAULTS, CSS_CLASSES } from '../../src/constants.js';
@@
-import { DEFAULTS } from '../../src/constants.js';

Also applies to: 42-42

🤖 Prompt for AI Agents
In demo/js/script.js around lines 6 and 42, there is a duplicate import of
DEFAULTS (imported at line 6 and again at line 42) and EVENTS is imported but
never used; remove the duplicate import and drop the unused EVENTS identifier so
the module only imports each symbol once and no unused symbols remain (keep a
single import that includes DEFAULTS and CSS_CLASSES as needed and remove the
second import at line 42 and the unused EVENTS from the import list).

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @p55d2k, please address this issue as it is breaking the demo.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

const controlPanel = document.getElementById('controlPanel');

const toggleStackCheckbox = document.getElementById('stackCheckbox');
Expand Down Expand Up @@ -38,7 +39,9 @@ let enableStackingBool = true;
let restrictDropzoneBool = true;

let ghostEffectBool = true;
let stackSpacingDefault = 10;
import { DEFAULTS } from '../../src/constants.js';

let stackSpacingDefault = DEFAULTS.STACK_SPACING_DEMO;

function initAllonsh(options) {
if (allonshInstance) {
Expand Down Expand Up @@ -95,8 +98,8 @@ function updateStackDirectionButtons() {
verticalStackBtn.classList.add('selected');
horizontalStackBtn.classList.remove('selected');
} else {
verticalStackBtn.classList.remove('selected');
horizontalStackBtn.classList.add('selected');
const draggableSelectorClass = CSS_CLASSES.DRAGGABLE;
const dropzoneSelectorClass = CSS_CLASSES.DROPZONE;
}
Comment on lines +101 to 103
Copy link

@coderabbitai coderabbitai bot Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Restore button state toggling for horizontal case.

The else-branch no longer toggles .selected classes; instead it declares unused locals. This regresses the UI feedback when switching back to horizontal.

Apply this diff:

   } else {
-    const draggableSelectorClass = CSS_CLASSES.DRAGGABLE;
-    const dropzoneSelectorClass = CSS_CLASSES.DROPZONE;
+    horizontalStackBtn.classList.add('selected');
+    verticalStackBtn.classList.remove('selected');
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const draggableSelectorClass = CSS_CLASSES.DRAGGABLE;
const dropzoneSelectorClass = CSS_CLASSES.DROPZONE;
}
} else {
horizontalStackBtn.classList.add('selected');
verticalStackBtn.classList.remove('selected');
}
🤖 Prompt for AI Agents
In demo/js/script.js around lines 101 to 103, the else-branch currently declares
unused locals (const draggableSelectorClass = CSS_CLASSES.DRAGGABLE; const
dropzoneSelectorClass = CSS_CLASSES.DROPZONE;) and no longer toggles the
'.selected' class for the horizontal layout, which breaks UI feedback; replace
those unused declarations with logic that finds the relevant draggable and
dropzone elements for the horizontal case and toggles (add/remove) the
CSS_CLASSES.SELECTED (or '.selected') class on them to match the behavior in the
other branch so that switching back to horizontal restores selected state.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@p55d2k, Please revert these changes so that the class toggle continues to function correctly.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

}

Expand Down Expand Up @@ -142,7 +145,7 @@ resetBtn.addEventListener('click', () => {
enableStackingBool = true;
restrictDropzoneBool = true;
ghostEffectBool = true;
stackSpacingDefault = 10;
stackSpacingDefault = DEFAULTS.STACK_SPACING_DEMO;
currentStackDirection = 'horizontal';
setDefaultsOnLoad();
updateStackDirectionButtons();
Expand Down Expand Up @@ -177,18 +180,20 @@ restrictDropzoneCheckbox.addEventListener('change', () => {
function logDraggablesOutsideDropzones() {
const playAreaElement = document.querySelector(`.${playAreaSelectorClass}`);

playAreaElement.querySelectorAll('.draggable').forEach((element) => {
if (
![...playAreaElement.querySelectorAll('.dropzone')].some((dropzone) =>
dropzone.contains(element)
)
) {
element.style.position = 'relative';
element.style.left = '';
element.style.top = '';
draggableContainer.appendChild(element);
}
});
playAreaElement
.querySelectorAll(`.${CSS_CLASSES.DRAGGABLE}`)
.forEach((element) => {
if (
![...playAreaElement.querySelectorAll(`.${CSS_CLASSES.DROPZONE}`)].some(
(dropzone) => dropzone.contains(element)
)
) {
element.style.position = 'relative';
element.style.left = '';
element.style.top = '';
draggableContainer.appendChild(element);
}
});
}

openPanelBtn.addEventListener('click', () => {
Expand All @@ -204,7 +209,7 @@ function togglePanel() {
}

function emptyDropzones() {
const dropzones = document.querySelectorAll('.dropzone');
const dropzones = document.querySelectorAll(`.${CSS_CLASSES.DROPZONE}`);
dropzones.forEach((dropzone) => {
while (dropzone.firstChild) {
dropzone.removeChild(dropzone.firstChild);
Expand Down
13 changes: 11 additions & 2 deletions docs/allonsh.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,24 @@ Allonsh dispatches the following custom events on relevant elements:

```js
import Allonsh from 'allonsh';
import { CSS_CLASSES, EVENTS } from 'allonsh/constants';

const dragDrop = new Allonsh({
draggableSelector: 'draggable',
dropzoneSelector: 'dropzone',
draggableSelector: CSS_CLASSES.DRAGGABLE,
dropzoneSelector: CSS_CLASSES.DROPZONE,
playAreaSelector: 'play-area',
Comment on lines +85 to 90
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify that allonsh/constants is actually exported.

The docs import from a subpath. Ensure your package.json “exports” includes "./constants"; otherwise consumers cannot import it.

Run:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
jq '.exports' package.json || { echo "No exports field"; exit 1; }
echo "Looking for ./constants subpath…"
jq -r '.exports|tostring' package.json | rg -n "\./constants" -n || echo "Missing ./constants export"

Length of output: 256


🏁 Script executed:

#!/bin/bash
# Find all files named constants.* in the repository
fd -t f 'constants.*'

Length of output: 70


Add subpath export for constants in package.json

The import import { CSS_CLASSES, EVENTS } from 'allonsh/constants' will fail because your package.json currently has no “exports” field (jq returned null), so consumers can’t resolve the constants subpath even though src/constants.js exists.

• File to update: package.json
• Action: add an exports map that exposes both the package root and the ./constants subpath.

Suggested diff (adjust paths to match your bundle outputs):

 {
   "name": "allonsh",
   "version": "1.0.0",
-  "main": "src/index.js",
+  "main": "src/index.js",
+  "exports": {
+    ".": "./src/index.js",
+    "./constants": "./src/constants.js"
+  },
   // …other fields…
 }

After this change, import { CSS_CLASSES } from 'allonsh/constants' will correctly resolve to your src/constants.js.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { CSS_CLASSES, EVENTS } from 'allonsh/constants';
const dragDrop = new Allonsh({
draggableSelector: 'draggable',
dropzoneSelector: 'dropzone',
draggableSelector: CSS_CLASSES.DRAGGABLE,
dropzoneSelector: CSS_CLASSES.DROPZONE,
playAreaSelector: 'play-area',
{
"name": "allonsh",
"version": "1.0.0",
"main": "src/index.js",
"exports": {
".": "./src/index.js",
"./constants": "./src/constants.js"
},
// …other fields…
}
🤖 Prompt for AI Agents
In docs/allonsh.md around lines 85 to 90, the example import from
'allonsh/constants' will fail because package.json lacks an "exports" map
exposing the ./constants subpath; update package.json to add an "exports" field
that maps the package root (".") and the "./constants" subpath to the
appropriate built files (e.g., "./dist/index.js" and "./dist/constants.js" or
your bundle output paths), ensuring both CommonJS and ESM entry points if needed
(provide "./dist/... .js" and "./dist/... .mjs" or use "require" and "import"
fields), and bump the package.json accordingly so import { CSS_CLASSES, EVENTS }
from 'allonsh/constants' resolves correctly.

restrictToDropzones: true,
enableStacking: true,
stackDirection: 'vertical',
stackSpacing: 10,
useGhostEffect: true,
});

// Listen for custom events
document.addEventListener(EVENTS.DRAG_START, (e) => {
// handle drag start
});
document.addEventListener(EVENTS.DROP, (e) => {
// handle drop
});
```
Loading