Coder Social home page Coder Social logo

pglejzer / timepicker-ui Goto Github PK

View Code? Open in Web Editor NEW
64.0 3.0 19.0 629 KB

timepicker-ui is an easy library with timepicker. Fully wrote with TypeScript. This library is based on Material Design from Google.

License: MIT License

JavaScript 3.15% SCSS 13.28% HTML 10.87% CSS 1.72% TypeScript 70.99%
material-design material design css javascript scss timepicker tyepscript

timepicker-ui's Introduction

timepicker-ui

downloads npm version License

timepicker-ui is an easy library with timepicker. Fully wrote with TypeScript. This library is based on Material Design from Google.

  • Free
  • Easy to use
  • Easy to customize

Click here to see a demo and examples


Desktop version

desktop-version

24h version

desktop-24h


Landspace version

desktop-version


Mobile version

mobile-version

Themes

There is 3 available version of theme: crane-straight, crane-radius and m3.

Theme m3 based on the new Material Design v3. Material Design 3 is still not release in offical version for WEB but you can use it if you want. There is new version of Material Design 3. If new version M3 will be released this design will get improve.

Desktop

desktop-crane-radius-version

Landspace

desktop-crane-radius-version-mobile

Mobile

desktop-crane-radius-version-mobile

Theme m3

desktop-m3-version

Theme m3-mobile

desktop-m3-version-mobile


Installation

Install timepicker-ui in your project.

Yarn

$ yarn add timepicker-ui

NPM

$ npm install timepicker-ui

This library is using font Roboto and material-design icons. Basic options for all icons have been taken from material-icons. If you want to use material-icons you have to add dependencies to your project.

You can alawys change icons to another package if you change options iconTemplate and iconTemplateMobile which contains templates for icons. iconTemplate and iconTemplateMobile requiare default class timepicker-ui-keyboard-icon.


Usage

Styles

We provide CSS styles built-in but sometimes if you don't use some normalize/reset CSS styles you have to add box-sizing: border-box to your app to display the correct layout.

*,
::after,
::before {
    box-sizing: border-box;
}

ES Modules

In your project you have to import timepicker from package to your JavaScript file.

import { TimepickerUI } from "timepicker-ui";

UMD

In your html file you have put script tag with path to timepicker-ui.umd.js file. After installing by npm/yarn you can copy the file from node_modules or add a path to this file.

<script src="timepicker-ui.umd.js"></script>
<script src="node_modules/path/timepicker-ui.umd.js"></script>
<script src="/path/timepicker-ui.umd.js"></script>
Information

timepicker-ui has to have a wrapper that has an input inside this wrapper. If you will not add class timepicker-ui to your wrapper, it will be automatically added during initialization.

HTML

<div class="timepicker-ui">
  <input type="text" class="timepicker-ui-input" value="12:00 AM" />
</div>

timepicker-ui has to be created with a new instance with key new. This instance accepts two parameters which first is the wrapper element for timepicker and the second is options that allow customization.

JavaScript

const DOMElement = document.querySelector(".timepicker-ui");
const options = {};
const newTimepicker = new TimepickerUI(DOMElement, options);

By default initialization of timepicker is started when you click on input. If you want to change it you have to add data-open attribute with selector inside and this element has to be inside wrapper.

To initalize a timepicker with UMD version you have to init a window object with tui.

const DOMElement = document.querySelector(".timepicker-ui");
const options = {};
const newTimepicker = new window.tui.TimepickerUI(DOMElement, options);

newTimepicker.create();

HTML

<div class="default-class">
  <input type="text" class="timepicker-ui-input" value="12:00 AM" />
  <button class="timepicker-ui-button" data-open="default-class">Open</button>
</div>

JavaScript

const timepicker = document.querySelector(".default-class");
const initTimepicker = new TimepickerUI(timepicker);

timepicker.create();

Options

You can set options by JavaScript or by data-attribute which attribute is a key option. Data-attributes will be overridden by JavaScript options.

HTML

<div
  class="default-class"
  data-am-label="test"
  data-backdrop="false"
  data-ok-label="fine"
>
  <input type="text" class="timepicker-ui-input" value="12:00 AM" />
  <button class="timepicker-ui-button" data-open="default-class">Open</button>
</div>

JavaScript

const timepicker = document.querySelector(".default-class");
const options = { okLabel: "test", amLabel: "test1", backdrop: false };
const initTimepicker = new TimepickerUI(timepicker, options);

timepicker.create();

CDNJS

This library is aviable in cdnjs packages. Here is a link to the full description https://cdnjs.com/libraries/timepicker-ui.

You can put script tags in your HTML file and use UMD version, without installation.

<script
  src="https://cdnjs.cloudflare.com/ajax/libs/timepicker-ui/2.3.0/timepicker-ui.umd.js"
  integrity="sha512-a3QUlKZYbhDBhA0b++tX+QjrbEwk1DNTyCR7rzwM34AUx16sNOLDzh4JQhqV5xYLs010+xsnFjrDjz2jx2+qLw=="
  crossorigin="anonymous"
  referrerpolicy="no-referrer"
></script>

React integration

It is possible to use this library on the React application. It's necessary to use the useRef hook to attach a dom element and add a custom event handler to this ref.

Link to an example with React Hooks.
Link to an example with React Class Component.

import React, { useRef, useEffect, useState, useCallback } from 'react';
import { TimepickerUI } from 'timepicker-ui';

function App(): JSX.Element {
  const tmRef = useRef(null);
  const [inputValue, setInputValue] = useState('12:00 PM');

  const testHandler = useCallback((e: CustomEvent) => {
    setInputValue(`${e.detail.hour}:${e.detail.minutes} ${e.detail.type}`);
  }, []);

  useEffect(() => {
    if (inputValue === "10:00 PM") {
      alert("You selected 10:00 PM");
    }
  }, [inputValue]);

  useEffect(() => {
    const tm = (tmRef.current as unknown) as HTMLDivElement;

    const newPicker = new TimepickerUI(tm, {});
    newPicker.create();

    //@ts-ignore
    tm.addEventListener('accept', testHandler);

    return () => {
      //@ts-ignore
      tm.removeEventListener('accept', testHandler);
    };
  }, [testHandler]);

  return (
    <div className='timepicker-ui' ref={tmRef}>
      <input
        type='test'
        className='timepicker-ui-input'
        defaultValue={inputValue}
      />
    </div>
  );
}

export default App;

Vue integration

This library can be used on Vue too. You have to use this.$refs to attach elements on DOM and add a custom event listener to this element.

Link to an example with Vue 2
Link to an example with Vue 3

<template>
  <div class="hello">
    <div class="timepicker-ui" ref="tm">
      <input v-model="inputValue" type="text" class="timepicker-ui-input" />
    </div>
    {{ inputValue }}
  </div>
</template>

<script>
import { TimepickerUI } from "timepicker-ui";

export default {
  name: "HelloWorld",
  data() {
    return {
      inputValue: "10:10 PM",
    };
  },
  mounted() {
    const test = new TimepickerUI(this.$refs.tm, { enableSwitchIcon: true });
    test.create();

    this.$refs.tm.addEventListener("accept", ({ detail }) => {
      this.inputValue = `${detail.hour}:${detail.minutes} ${detail.type}`;
    });
  },
};
</script>

Table with options

Name Default Type Description
animation true boolean Turn on/off animations on picker on start/close
amLabel AM string You can set custom text to am label
appendModalSelector '' string You can set default selector to append timepicker inside it. Timepicker default append to body
backdrop true boolean Turn on/off backdrop
cancelLabel CANCEL string You can set custom text to cancel button
clockType 12h string You can set type of clock, it contains 2 versions: 12h and 24h.
editable false boolean Edit hour/minutes on the web mode.
enableScrollbar false boolean Turn on/off scroll if timepicker is open
enableSwitchIcon false boolean Turn on/off icon to switch desktop/mobile
focusInputAfterCloseModal false boolean Turn on/off focus to input after close modal
focusTrap true boolean Turn off/on focus trap to the picker
hourMobileLabel Hour string You can set custom text to hour label on mobile version
incrementHours 1 nubmer Increment hour by 1, 2, 3 hour
incrementMinutes 1 nubmer Increment minutes by 1, 5, 10, 15 minutes
minuteMobileLabel Minute string You can set custom text to minute label on mobile version
mobile false boolean Turn on mobile version
mobileTimeLabel Enter Time string You can set custom text to time label on mobile version
okLabel OK string You can set custom text to ok label
pmLabel PM string You can set custom text to pm label
timeLabel Select Time string You can set custom text to time label on desktop version
switchToMinutesAfterSelectHour true boolean Turn on/off switch to minutes by select hour
iconTemplate <i class="material-icons timepicker-ui-keyboard-icon"> keyboard </i> string You can set default template to switch desktop.This options is using by default material design icon
iconTemplateMobile <i class="material-icons timepicker-ui-keyboard-icon"> schedule </i> string You can set default template to switch mobile. This options is using by default material design icon
theme basic string You can set theme to timepicker. Available options: basic, crane-straight, crane-radius and m3.
The offical version of Material Design 3 is still not avaialbe for the WEB version. Theme m3 has been added based on the design what you can find here. If new version M3 will be released this design will get improve.
disabledTime undefined object This option allows 3 keys: hours, minutes and interval. The hours and minutes are arrays which accept strings and numbers to block select hours/minutes. The interval key allow only string with interval values i.e., if you have 24h clockType the string can be 03:00 - 15:00, 01:20 - 05:15, 02:03 - 06:55 etc.. On the other hand if you have 12h clockType the string can be i.e 01:30 PM - 6:30 PM, 02:00 AM - 10:00 AM, 02:30 AM - 10:30 PM. It is important to remember that first hour in the interval option should be less that the second value if you want to block values from AM to PM and if you are using interval with 24h clockType. If the interval key is set, the hours/minutes keys are ignored.
currentTime undefined boolean | object Set current time to the input and timepicker.
If this options is set to true it's gonna update picker with toLocaleTimeString() and input with value based on your location. The clockType option is forced in that case.
This option also allows to put object with properties which:
  • The updateInput key is set to true it's going update input value with the setted time key.
  • The time key allows to put any valid date to update picker with time. It's converting Date to time.
    If the updateInput is set to false/undefined and the default value from the input not exist, the time key value will be displayed in the picker.
    If the updateInput is set to false/undefined but the default value from the input exist, the time key will be ignored.
  • The localeskey can change language from toLocaleTimeString().
  • The preventClockType key if is set to true it's force the clockType option to set value "12h" or "24h" based on your location with current time and locales key value is ignored in that case.
    currentTime: { time: new Date(), updateInput: true, locales: "en-US", preventClockType: false };
delayHandler 300 number Set delay to clickable elements like button "OK", "CANCEL" etc. The value has to be set in milliseconds.

Methods

Methods are custom function what can be used to manually change the behavior of timepicker.

HTML

<div class="timepicker-ui-test">
  <input type="text" class="timepicker-ui-input" value="12:00 AM">
</div>

JavaScript

const timepicker = document.querySelector("timepicker-ui-test");
const init = new TimepickerUI(timepicker);

timepicker.create();

Table with methods

Name Description Parameters Default Parameters description
create The create method init timepicker - - -
open The open method opens immediately timepicker after init (function) undefined The callback function is tiggered when timepicker is open by this method.

Example:
tmInstance.open(()=> console.log('triggered after open'));
close Closure method closes the timepicker ()(boolean, function) undefined The first parentheses doesn't have any paremeters. The second parentheses accepts parameters and these parameters are optional in this method and order is any. You can set callback function first or boolean, or just boolean or just callback. If the boolean is set to true the input will be updating with the current value on picker. The callback function start immediately after close, if is invoke. The max parameters length are set to 2

Examples:
tmInstance.close()(() => console.log('triggered after close'));
tmInstance.close()(true, () => console.log('triggered after close'));
tmInstance.close()(true);
update The update method (object, function) ({ options: {}, create: boolean }, callback) The first parameter is a object with key options which is timepicker options and it will be updated to current instance and is `required` The `create` key wchich if is set to true is starting the create() method after invoke update function and is optional. The `create` option is useful if you are using destroy and update methods together. The callback function is triggered after update method is invoke and this parameter is optional.

Examples:
tmInstance.update({options:{ amLabel:"test" }}, () => console.log('triggered after update'));
tmInstance.update({options:{ amLabel:"test" }, create: true}, () => console.log('triggered after update'));
tmInstance.update({options:{ amLabel:"test" });
destroy The destroy method destroy actual instance of picker by cloning element. (function) undefined The callback function is started after destroyed method. This parameter is optional.

Example:
tmInstance.destroy(() => console.log('triggered after destroy'));

Events

Events are custom events triggered when you add some event listeners to your timepicker element. If you want to have a property timepicker/input values you have to use detail to the event object.

HTML

<div class="timepicker-ui-test">
  <input type="text" class="timepicker-ui-input" value="12:00 AM">
</div>

JavaScript

const timepicker = document.querySelector("timepicker-ui-test");
const init = new TimepickerUI(timepicker);

timepicker.create();

timepicker.addEventListener("show", (event) => console.log(event.detail));

Table with events

Name Description
show The event starts if timepicker is showing up
cancel The event starts if timepicker is closing
accept The event starts if timepicker button OK is accepted
update The event starts if mouse/touch events are triggered on a clock face (multiple events)
selectminutemode The event starts if timepicker minute box is clicked
selecthourmode The event starts if timepicker hour box is clicked
selectamtypemode The event starts if timepicker am box is clicked
selectpmtypemode The event starts if timepicker pm box is clicked
geterror The event start if value in the input is wrong

Future Plans

  • keyboard accesibilty
  • max/min time options

If you have more good ideas please let me know in issue. I will try to add more useful features. This project is still develop, if you find some bugs please report on the issue page.


License

MIT

timepicker-ui's People

Contributors

grizzlymannn avatar pglejzer avatar q448x avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

timepicker-ui's Issues

Can I have multiple instances of the timepicker on the same page?

Hello,

I've tried to use different timepickers on multiple fields and it's not working as expected. I tried using in the initialization the id instead of the class or creating unique classes
When I select the minute the hour changes as well.
Can you advise? Maybe I'm doing something wrong, or this isn't a supported feature.

Can't build from sourัe

Hi,
thanks a lot foะบ the wonderful tool. The question is probably my bad knowledge of js machinery.

  1. Cloned repo in my Laravel project
  2. npm run build, i.e. "build": "webpack && rollup -c",
ERROR in ./docs/index.ts 30:45
Module parse failed: Unexpected token (30:45)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| currentDate.setMinutes(0);
| 
> const test = document.querySelector('.test') as HTMLDivElement;

it seems something is missing from my webpack installation.

'accept' event doesn't trigger when switching modes

Hi there! I've got the library running in Angular 14 (wasn't too challenging) but it seems that the 'accept' event is not triggering when pressing OK after switching the mobile mode using the switch icon (either direction). Possibly something to do with destroying and initializing a new instance of the element - would that lose any event listeners tied to the original element?

[FEATURE] It will be nicer if we can set the time by typing numbers.

I noticed that we can type in numbers to the minutes and hour in the mobile mode, why not allow doing this in other mode? I think it is better to add an options to determine if those div can be edit, instead limits the behaviour in a particular mode.

And I think it is better if user can adjusts timepicker's value through scrolling over the clockface and the <div />s.

"switchToMinutesAfterSelectHour" on mobile

When "switchToMinutesAfterSelectHour" is on "true", if I'm on a mobile and I try de go back the the hours it directly switch to the minutes. It's impossible to change the hours, it jumps back automaticaly and immediatly on the minutes.

How can i use it in a normal typescript project?

I've created a normal typescript project and I've done everything the starter file tells me to do.
But while importing it in my ts file , i get this error :
error TS2792: Cannot find module 'timepicker-ui'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option?
then I add "moduleResolution": "Node" in tsconfig.json , i get this error in the browser Uncaught TypeError: Failed to resolve module specifier "timepicker-ui". Relative references must start with either "/", "./", or "../". .

this is the tsconfig.json :
`{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */

/* Projects */
// "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */

/* Language and Environment */
"target": "ES2015",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve",                                /* Specify what JSX code is generated. */
// "experimentalDecorators": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */

/* Modules */
"module": "ES6",                                /* Specify what module code is generated. */
// "rootDir": "./",                                  /* Specify the root folder within your source files. */
"moduleResolution": "Node",                       /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
// "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
// "resolveJsonModule": true,                        /* Enable importing .json files. */
// "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */

/* JavaScript Support */
// "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */

/* Emit */
// "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
// "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
"outDir": "./dist",                                   /* Specify an output folder for all emitted files. */
// "removeComments": true,                           /* Disable emitting comments. */
// "noEmit": true,                                   /* Disable emitting files from a compilation. */
// "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types. */
// "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf",                                /* Set the newline character for emitting files. */
// "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
// "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */

/* Interop Constraints */
// "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */

/* Type Checking */
"strict": true,                                      /* Enable all strict type-checking options. */
// "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */
// "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */

/* Completeness */
// "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true                                 /* Skip type checking all .d.ts files. */

},
"include":["src"]
}
`

This is the package.json file :
{ "name": "testing_timepicker", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "lite-server" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "timepicker-ui": "^2.5.0" }, "devDependencies": { "lite-server": "2.3", "ts-loader": "^9.4.1", "typescript": "^4.8.4", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" } }

Switching mobile and desktop in 24h mode doesn't auto-reopen the clock

If you set the timepicker in 24h mode, when you try to switch to mobile and viceversa, the picker doesn't reopen itself.
An error is written in console:

Cannot read properties of null (reading 'dataset'),

I saw that "this.activeTypeMode" is null.

When you are not using the 24h mode, the picker reopens itself but the following error is fired in console:
e.map is not a function

Issue changing hour

I'm using the timepicker with the following configuration:

{
			cancelLabel: 'cancel',
			clockType: '24h',
			mobile: false,
			okLabel: 'ok',
			hourMobileLabel: '',
			minuteMobileLabel: '',
			mobileTimeLabel: 'select time',
			selectTimeLabel: 'select time',
			backdrop: true,
			editable: true,
			preventDefault: false,
			enableSwitchIcon: true,
			iconTemplate: '<div class="keyboard-time"></div>',
			iconTemplateMobile: '<div class="clock-time"></div>'
		}

If I do the following steps:

  1. open the picker
  2. select an high hour (p.e. 15)
  3. change picker type (bottom left button)
  4. click on the hour (trying to typing the hour)
    I receive the following error in console:
    Uncaught TypeError: Cannot read properties of null (reading 'classList') at y._setCircleClockClasses24h

If I do the following steps:

  1. open the picker
  2. select an high hour (p.e. 15)
  3. change picker type (bottom left button)
  4. change again the picker time
  5. press 'ok'
  6. try to open again the picker

I receive the following error in console (and the picker doesn't open anymore):
Uncaught TypeError: Cannot read properties of null (reading 'classList') at y._setCircleClockClasses24h

Enable multiple instance creation

When you have a form with multiple inputs in time format would be if new TimepickerUI(DOMElement, options); initialize all of them at the same time. At the moment, it only initialize the first input of querySelector result.

How to convert this code in typescript?

I am new to typescript. I am struggling with this particular code of Accept Event to typescript.
this.acceptEvent.addEventListener( "accept", ({ detail: { hour, minutes, type } }) => this.time = ${hour}:${minutes} ${type} );
I am struggling to define the type of "detail";

Can't add multiple disabledTime Intervals ?

I want to disabled multiple time slots like

'09:00 AM - 09:30 AM' , '10:00 AM - 10:30 AM'
like I want to disable above to time slots from 9 am to 9 30 am and 10 am to 10 30 am , and like above I have just 2 time slots but can have multiple slots
how do I add multiple disabledTime intervals as it's the string below is my code

import { TimepickerUI } from "timepicker-ui";




const basic = document.querySelector(".basic");
const options = {
   // currentTime: {
   //     updateInput: true,
   //     locales: "en-US",
   //     preventClockType: false
   // },
   clockType: "12h",
   theme: "basic",
   incrementMinutes: 15,
   disabledTime: {
       interval: '10:00 AM - 10:30 AM',
       interval: '10:00 AM - 10:30 AM',
   },
  
   // mobile: true,
};
const basicPicker = new TimepickerUI(basic, options);
basicPicker.create();

  

Unable to delete time on Firefox

On FireFox, if you type directly the time into the time boxes, you cannot manually delete what you have written (cancel and backspace buttons don't do nothing)

CDNJS not working.

    I have this problem now :/

timeline:155 Uncaught ReferenceError: TimepickerUI is not defined
at HTMLDocument.

I added this in head, also tried to add it to the html file and yet didn't work:

<script src="https://cdnjs.cloudflare.com/ajax/libs/timepicker-ui/2.3.0/timepicker-ui.umd.js" integrity="sha512-a3QUlKZYbhDBhA0b++tX+QjrbEwk1DNTyCR7rzwM34AUx16sNOLDzh4JQhqV5xYLs010+xsnFjrDjz2jx2+qLw==" crossorigin="anonymous" referrerpolicy="no-referrer" ></script>

Originally posted by @8WiaM8 in #43 (comment)

cannot read property classList of null when using mobile in developer tools

When I try the demo page [https://q448x.github.io/timepicker-ui-docs/] in chrome in developer mode, setting the device toolbar to an android phone, the clockface control gives an error. Changing the hour hand causes an error "cannot read properly classList of null", and then sets the displayed time to NaN.

This does not happen when I set the device to iPhone. It also didn't happen on my actual android phone, so maybe there isn't an issue here at all, but I'm uneasy about deploying this in production when it doesn't work in developer mode.

(the mobile setting works fine, but I prefer the clockface, even on mobile)

"0NaN" error when using touch input

This only seems to happen on my laptop that has a touch screen. Doesn't happen on phone or tablet when using touch. Also doesn't happen on laptop when using mouse input.

When picking hour or minute using laptop touchscreen the corresponding hour or minute section becomes blank and this error occurs.

The specified value "0NaN" cannot be parsed, or is out of range. _handleEventToMoveHand @ timepicker-ui.umd.js:1 _mutliEventsMove @ timepicker-ui.umd.js:1

These are the options used when creating the TimepickerUI object.
const option = { mobile: false, };

[REQUEST] Destroy the picker or change some options

Hi,
I have a request.

I need to dynamically change some timepicker options such as the labels of the picker. If I create twice the picker, 2 instances overlaps so it doesn't work well (for example, changing the minutes, changes also the hour).
So it could be nice to have a method to destroy the current instance and to create another one using the same input.

Another way to achieve my goal would be to add the possibility to change some picker options once the picker has been created (but I think it's more complicated).

Thank you

Feature request - use timepicker outside modal

It would be great to be able to easily use this along side other elements on the page, instead of having to use this in a modal. If this is already available or someone knows a way to do it, please respond!

Using with React

When using this library with React in strict mode, the destroy method violates the logic of the component.
Due to the fact that the element is cloned in the destroy method, it no longer belongs to the ref object in the react component.

The documentation states to use:

import React, { useRef, useEffect, useState, useCallback } from 'react';
import { TimepickerUI } from 'timepicker-ui';

function App(): JSX.Element {
  const tmRef = useRef(null);
  const [inputValue, setInputValue] = useState('12:00 PM');

  const testHandler = useCallback((e: CustomEvent) => {
    setInputValue(`${e.detail.hour}:${e.detail.minutes} ${e.detail.type}`);
  }, []);

  useEffect(() => {
    if (inputValue === "10:00 PM") {
      alert("You selected 10:00 PM");
    }
  }, [inputValue]);

  useEffect(() => {
    const tm = (tmRef.current as unknown) as HTMLDivElement;

    const newPicker = new TimepickerUI(tm, {});
    newPicker.create();

    //@ts-ignore
    tm.addEventListener('accept', testHandler);

    return () => {
      //@ts-ignore
      tm.removeEventListener('accept', testHandler);
    };
  }, [testHandler]);

  return (
    <div className='timepicker-ui' ref={tmRef}>
      <input
        type='test'
        className='timepicker-ui-input'
        defaultValue={inputValue}
      />
    </div>
  );
}

export default App;

My usage example:

function TimePickerInput (): JSX.Element {
  const tmRef = useRef(null);
  const [inputValue, setInputValue] = useState('12:00 PM');

  const testHandler = useCallback((e: CustomEvent) => {
    setInputValue(`${e.detail.hour}:${e.detail.minutes} ${e.detail.type}`);
  }, []);

  useEffect(() => {
    if (inputValue === "10:00 PM") {
      alert("You selected 10:00 PM");
    }
  }, [inputValue]);

  useEffect(() => {
    const tm = tmRef.current;
    const newPicker = new TimepickerUI(tm, {});
    newPicker.create();

    tm.addEventListener('accept', testHandler);

    return () => {
      if (tm)
        tm.removeEventListener('accept', testHandler);
      tm.destroy()
    };
  }, [testHandler]);

  return (
    <div className='timepicker-ui' ref={tmRef}>
      <input
        type='test'
        className='timepicker-ui-input'
        defaultValue={inputValue}
      />
    </div>
  );
  
  function App(): JSX.Element {
    return <React.StrictMode>
      <TimePickerInput />
    </React.StrictMode>
  }
  
  export default App;
}

In this case, as I showed above, there will be a problem when re-rendering in strict mode.
After the initial call of the destroy method, tmRef.current will contain a reference to an element that no longer exists.

To fix this, you need to constantly update the link to the element. For example, this can be done using the id for the html element:

function TimePickerInput(): JSX.Element {
  const tmRef = useRef(null);
  const [elementId] = useState(useId().replaceAll(':') + '__timepicker')
  const [inputValue, setInputValue] = useState('12:00 PM');

  // ...

  useEffect(() => {
    tmRef.current = document.querySelector('#' + elementId)
  })
  
  // ...

  return (
    <div className='timepicker-ui' ref={tmRef} id={elementId}>
      <input
        type='test'
        className='timepicker-ui-input'
        defaultValue={inputValue}
      />
    </div>
  );
}

// ...

Or in any other way to store an up-to-date reference to the element.

Such use does not seem very convenient. Do you know another way to avoid such problems?

Archived repo? Unmaintained?

Would like to use this nice looking picker,
but repo looks unmaintained with open issues and unmerged bug fixes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.