Skip to content

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.

js
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.

ParamTypeDefaultDescription
codestringThe target combination as a digit string (e.g. '0042', '000006'). Length is variable
js
const padlock = new NssPadLock('1234');   // 4-digit lock
const padlock = new NssPadLock('000000'); // 6-digit lock

Methods

.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.

js
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.

js
padlock.hide().then(() => {
    padlock.destroy();
    nss_client.close();
});

.destroy()

Removes the padlock DOM from the document.

Returns undefined

js
padlock.hide().then(() => {
    padlock.destroy();
});

.openLock()

Animates the shackle opening.

Returns Promise<void> — resolves when the animation completes.

js
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

js
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.

js
const entered_code = padlock.getCode(); // e.g. '0042'

.onOpen(callback)

Registers a callback that fires when the lock successfully opens (automatic mode only).

ParamTypeDefaultDescription
callbackNssPadLock~onOpenCalled with the padlock instance

Returns NssPadLock — chainable.

js
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.

ParamTypeDefaultDescription
callbackNssPadLock~onNewCodeCalled with the entered code string

Returns NssPadLock — chainable.

js
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.

js
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().

ParamTypeDefaultDescription
uidstringA unique identifier for this lock instance (e.g. chest ID)
duration_msnumberCache duration in milliseconds

Returns NssPadLock — chainable.

js
padlock.enableCache('chest_42', 60000); // Cache for 1 minute

.setTimePenalty(ms)

Sets the delay after a wrong code before the rollers are re-enabled.

ParamTypeDefaultDescription
msnumberPenalty duration in milliseconds

Returns NssPadLock — chainable.

js
padlock.setTimePenalty(3000); // 3 second penalty

.setNotClosable()

Prevents the lock from being closable via the close button.

Returns NssPadLock — chainable.

js
padlock.setNotClosable();

.setTranslationUnlock(text) / .setTranslationLock(text)

Sets the label text for the unlock and lock buttons.

ParamTypeDefaultDescription
textstringThe button label

Returns NssPadLock — chainable.

js
padlock.setTranslationUnlock('Open').setTranslationLock('Close');

.disableButtons() / .enableButtons()

Disables or enables the unlock button. Use after onNewCode to prevent double-submits.

Returns undefined

js
padlock.onNewCode((code) => {
    padlock.disableButtons();
    nss_client.post('validate', {code: code}, () => {
        padlock.enableButtons();
    });
});

Usage Patterns

js
const padlock = new NssPadLock('0042');
padlock
    .setTimePenalty(3000)
    .setTranslationUnlock('Unlock')
    .setTranslationLock('Lock')
    .onOpen((lock) => {
        lock.hide().then(() => lock.destroy());
    })
    .show();
js
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();
    }
});
js
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.
  • Audiocombi-lock-click.mp3 on digit change, combi-lock-open.mp3 on lock toggle.

CSS

Classes

ClassDescription
.combi-lockRoot container
.combi-lock--visibleVisible state
.combi-lock__slide-in / __slide-outEntry/exit animation triggers
.combi-lock--errorError state (shake on __inner)
.combi-lock__innerInner body with decorative overlay
.combi-lock__closerShackle element
.combi-lock__closer--openOpen state (45deg rotation)
.combi-lock__rollersGrid container for roller columns
.combi-lock__rollerIndividual roller column
.combi-lock__carousel3D rotating number cylinder
.combi-lock__numberIndividual digit face
.combi-lock__unlock-btnUnlock button

Custom Properties

PropertyDefaultDescription
--combi-lock-anim-dur500msSlide in/out animation duration
--combi-lock-error_anim-dur800msShake animation duration
--factor3.15Scale factor for the lock
--slide-number-heightcalc(var(--1rpx) * 30)Roller digit height
--slide-number-widthcalc(var(--1rpx) * 40)Roller digit width

Animations

KeyframeDescription
combi-lock-anim__slide-in-topSlides in from top + fade
combi-lock-anim__slide-out-bottomSlides out to bottom + fade
combi-lock-anim__shakeHorizontal shake for error state

Dependencies

  • NssUiComponent — base class (initializes NssResponsive).
  • 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.

NIGHTSHIFT STUDIO Documentation