NssPadLock
An interactive combination lock PIN entry UI with roller animation, cache support, and server validation. NUI
Getting Started
NssPadLock emulates a physical combination lock. Users drag number rollers to enter a code, then press unlock. The lock can operate in automatic mode (checks code internally), custom mode (server validates), or with a code cache.
import {NssUiApi} from "nui://nss_libs/ui/NssUiApi.js";
nss_ui_api.load([NssUiApi.NssPadLock, NssUiApi.NssClient]).then((components) => {
const padlock = new components.NssPadLock('0000');
padlock
.setTranslationUnlock('Unlock')
.setTranslationLock('Lock')
.onOpen((lock) => { console.log('Lock opened!'); })
.show();
});Constructor
new NssPadLock(code)
Creates a padlock with the given target code. The code length determines the number of rollers.
| Param | Type | Default | Description |
|---|---|---|---|
code | string | — | The target combination as a digit string (e.g. '0042', '000006'). Length is variable |
const padlock = new NssPadLock('1234'); // 4-digit lock
const padlock = new NssPadLock('000000'); // 6-digit lockMethods
.show()
Displays the padlock with a slide-in animation. If cache is enabled and a valid cached code exists, it auto-enters the code and simulates an unlock click.
Returns Promise<void> — resolves when the animation completes.
padlock.show().then(() => {
console.log('Padlock is visible');
});.hide()
Hides the padlock with a slide-out animation.
Returns Promise<void> — resolves when the animation completes.
padlock.hide().then(() => {
padlock.destroy();
nss_client.close();
});.destroy()
Removes the padlock DOM from the document.
Returns undefined
padlock.hide().then(() => {
padlock.destroy();
});.openLock()
Animates the shackle opening.
Returns Promise<void> — resolves when the animation completes.
padlock.openLock().then(() => {
padlock.hide();
});.wrongCode()
Plays the error sequence: close lock → shake → reset rollers. Buttons are re-enabled after the time penalty.
Returns undefined
nss_client.on('validation_result', (data) => {
if (data.is_valid) {
padlock.openLock().then(() => padlock.hide());
} else {
padlock.wrongCode();
}
});.getCode()
Returns the current dial combination as a string.
Returns string — the currently entered code.
const entered_code = padlock.getCode(); // e.g. '0042'.onOpen(callback)
Registers a callback that fires when the lock successfully opens (automatic mode only).
| Param | Type | Default | Description |
|---|---|---|---|
callback | NssPadLock~onOpen | — | Called with the padlock instance |
Returns NssPadLock — chainable.
padlock.onOpen((lock) => {
lock.hide().then(() => lock.destroy());
});.onNewCode(callback)
Registers a callback that fires every time the user attempts to unlock. Used in custom mode.
| Param | Type | Default | Description |
|---|---|---|---|
callback | NssPadLock~onNewCode | — | Called with the entered code string |
Returns NssPadLock — chainable.
padlock.onNewCode((code) => {
padlock.disableButtons();
nss_client.post('validate_code', {entered_code: code});
});.disableAutomation()
Disables automatic code validation. You must manually handle onNewCode and call openLock() / wrongCode().
Returns NssPadLock — chainable.
padlock.disableAutomation().onNewCode((code) => {
// Send code to server for validation
nss_client.post('validate', {code: code});
});.enableCache(uid, duration_ms)
Enables code caching. If the lock was previously opened with the same uid, the cached code is auto-entered on show().
| Param | Type | Default | Description |
|---|---|---|---|
uid | string | — | A unique identifier for this lock instance (e.g. chest ID) |
duration_ms | number | — | Cache duration in milliseconds |
Returns NssPadLock — chainable.
padlock.enableCache('chest_42', 60000); // Cache for 1 minute.setTimePenalty(ms)
Sets the delay after a wrong code before the rollers are re-enabled.
| Param | Type | Default | Description |
|---|---|---|---|
ms | number | — | Penalty duration in milliseconds |
Returns NssPadLock — chainable.
padlock.setTimePenalty(3000); // 3 second penalty.setNotClosable()
Prevents the lock from being closable via the close button.
Returns NssPadLock — chainable.
padlock.setNotClosable();.setTranslationUnlock(text) / .setTranslationLock(text)
Sets the label text for the unlock and lock buttons.
| Param | Type | Default | Description |
|---|---|---|---|
text | string | — | The button label |
Returns NssPadLock — chainable.
padlock.setTranslationUnlock('Open').setTranslationLock('Close');.disableButtons() / .enableButtons()
Disables or enables the unlock button. Use after onNewCode to prevent double-submits.
Returns undefined
padlock.onNewCode((code) => {
padlock.disableButtons();
nss_client.post('validate', {code: code}, () => {
padlock.enableButtons();
});
});Usage Patterns
const padlock = new NssPadLock('0042');
padlock
.setTimePenalty(3000)
.setTranslationUnlock('Unlock')
.setTranslationLock('Lock')
.onOpen((lock) => {
lock.hide().then(() => lock.destroy());
})
.show();const padlock = new NssPadLock('0000'); // Dummy code, server validates
padlock
.setTimePenalty(3000)
.setTranslationUnlock('Unlock')
.setTranslationLock('Lock')
.disableAutomation()
.setNotClosable()
.onNewCode((code) => {
padlock.disableButtons();
nss_client.post('validate_code', {entered_code: code});
})
.show();
nss_client.on('validation_result', (data) => {
if (data.is_valid) {
padlock.openLock().then(() => padlock.hide().then(() => padlock.destroy()));
} else {
padlock.wrongCode();
}
});padlock
.onOpen((lock) => { lock.hide(); })
.enableCache('storage_42', 60000)
.show();Events / Callbacks
- onOpen(callback) — fires when the lock is successfully opened (automatic mode).
- onNewCode(callback) — fires on every unlock attempt (custom mode). Receives the code string.
- Audio —
combi-lock-click.mp3on digit change,combi-lock-open.mp3on lock toggle.
CSS
Classes
| Class | Description |
|---|---|
.combi-lock | Root container |
.combi-lock--visible | Visible state |
.combi-lock__slide-in / __slide-out | Entry/exit animation triggers |
.combi-lock--error | Error state (shake on __inner) |
.combi-lock__inner | Inner body with decorative overlay |
.combi-lock__closer | Shackle element |
.combi-lock__closer--open | Open state (45deg rotation) |
.combi-lock__rollers | Grid container for roller columns |
.combi-lock__roller | Individual roller column |
.combi-lock__carousel | 3D rotating number cylinder |
.combi-lock__number | Individual digit face |
.combi-lock__unlock-btn | Unlock button |
Custom Properties
| Property | Default | Description |
|---|---|---|
--combi-lock-anim-dur | 500ms | Slide in/out animation duration |
--combi-lock-error_anim-dur | 800ms | Shake animation duration |
--factor | 3.15 | Scale factor for the lock |
--slide-number-height | calc(var(--1rpx) * 30) | Roller digit height |
--slide-number-width | calc(var(--1rpx) * 40) | Roller digit width |
Animations
| Keyframe | Description |
|---|---|
combi-lock-anim__slide-in-top | Slides in from top + fade |
combi-lock-anim__slide-out-bottom | Slides out to bottom + fade |
combi-lock-anim__shake | Horizontal shake for error state |
Dependencies
NssUiComponent— base class (initializesNssResponsive).NssAudio— lock interaction sounds.
Things to Know
INFO
Input is mouse drag (vertical) on the rollers. The roller snaps to the nearest digit on mouse-up.
WARNING
In automatic mode, the code passed to the constructor is the correct code. In custom mode (disableAutomation()), the constructor code only defines the number of digits — use a dummy like '0000'.
- The cache is stored as a static class property — it survives instance destruction but not page reloads.
wrongCode()includes the full error sequence: close → shake → reset → re-enable with penalty delay.
