simple-keyboard/simple-keyboard-layouts

ipad iOS keyboard QWERTY layout

MadDeveloper opened this issue ยท 12 comments

Sorry about doing this in a issue, but I don't see where I can do it elsewhere ๐Ÿ˜…
I'm creating an issue in this project because of its name, but the files inside it don't indicate where I can put the following layout code. So I post it here, and I let you tell me where it can goes:

// ipad iOS QWERTY layout
const layout = {
  default: [
    'q w e r t y u i o p {bksp}',
    'a s d f g h j k l {enter}',
    '{shift} z x c v b n m , . {shift}',
    '{alt} {smileys} {space} {altright} {downkeyboard}'
  ],
  shift: [
    'Q W E R T Y U I O P {bksp}',
    'A S D F G H J K L {enter}',
    '{shiftactivated} Z X C V B N M , . {shiftactivated}',
    '{alt} {smileys} {space} {altright} {downkeyboard}'
  ],
  alt: [
    '1 2 3 4 5 6 7 8 9 0 {bksp}',
    `@ # $ & * ( ) ' " {enter}`,
    '{shift} % - + = / ; : ! ? {shift}',
    '{default} {smileys} {space} {back} {downkeyboard}'
  ],
  smileys: [
    '๐Ÿ˜€ ๐Ÿ˜Š ๐Ÿ˜… ๐Ÿ˜‚ ๐Ÿ™‚ ๐Ÿ˜‰ ๐Ÿ˜ ๐Ÿ˜› ๐Ÿ˜  ๐Ÿ˜Ž {bksp}',
    `๐Ÿ˜ ๐Ÿ˜ฌ ๐Ÿ˜ญ ๐Ÿ˜“ ๐Ÿ˜ฑ ๐Ÿ˜ช ๐Ÿ˜ฌ ๐Ÿ˜ด ๐Ÿ˜ฏ {enter}`,
    '๐Ÿ˜ ๐Ÿ˜‡ ๐Ÿคฃ ๐Ÿ˜˜ ๐Ÿ˜š ๐Ÿ˜† ๐Ÿ˜ก ๐Ÿ˜ฅ ๐Ÿ˜“ ๐Ÿ™„ {shift}',
    '{default} {smileys} {space} {altright} {downkeyboard}'
  ]
}
@import '../../assets/styles/variables';

/**
 * hg-theme-default theme
 */
.simple-keyboard {
  width: 750px;
  margin: auto;

  .hg-button {
    display: inline-block;
    flex-grow: 1;
    cursor: pointer;
  }

  .hg-row {
    display: flex;

    &:not(:last-child) {
      margin-bottom: $keyboard-margins;
    }

    .hg-button:not(:last-child) {
      margin-right: $keyboard-margins;
    }

    &:nth-child(2) {
      margin-left: 18px;
    }
  }

  &.hg-theme-default {
    background-color: rgba(0, 0, 0, 0.1);
    padding: 5px;
    border-radius: 5px;

    &.hg-layout-custom {
      background-color: $keyboard-background-color;
      padding: 5px;
    }

    .hg-button {
      border-radius: 5px;
      box-sizing: border-box;
      padding: 0;
      background: white;
      border-bottom: 1px solid #b5b5b5;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      box-shadow: none;
      font-weight: 400;
      font-size: 20px;
      max-width: 60px;
      min-width: 60px;
      height: 60px;
      min-height: 60px;

      &:active,
      &:focus {
        background: #e4e4e4;
      }

      &.hg-functionBtn {
        background-color: $keyboard-button-action-color;
      }

      &.hg-button-space,
      &.hg-button-shift,
      &.hg-button-shiftactivated {
        background-color: #ffffff;
      }
    }

    .hg-button-space {
      max-width: 448px;
      min-width: 448px;
    }

    .hg-button-enter {
      max-width: 110px;
      min-width: 110px;
    }

    .hg-button-altright,
    .hg-button-back {
      min-width: 80px;
      max-width: 80px;
    }
  }
}

All sizes are fixed in order to have a better design, but can be readapted following the needs.

And the key press logic:

const isFunctionButton = names => button => [...names].includes(button)
const isShiftButton = isFunctionButton(['{shift}', '{shiftactivated}'])
const isAltButton = isFunctionButton(['{alt}', '{altright}'])
const isSmileysButton = isFunctionButton(['{smileys}'])
const isDefaultButton = isFunctionButton(['{default}'])

Here is what it looks:
iPad iOS QWERTY layout

Is there a place where all keyboards are organised by layout or by language? For example: where I can find the layout iPad iOS QWERTY or AZERTY? Idem for iOS devices, Android, etc.

Hello @MadDeveloper,

That's a good question. I think I would have to consider revamping simple-keyboard-layouts as it currently only returns a "layout" property for simple-keyboard to use. This fits the initial purpose of this plugin, which is to provide layouts in different languages. Check here for more info.

Currently, to show a specific demo (I call it a "use-case"), I do these steps:

  1. Fork this sandbox (for vanilla JS) or this one for React.
  2. Adapt-it to the use case.
  3. Then, I export this repo to my github like so:

image

  1. This generates a sandbox URL which is linked to the repo, like this one.

  2. Finally, this demo is added to the main Demos Page.

This has the benefit of keeping the core codebase light, as anyone can just copy/fork whatever demo they are interested in and not have to import use-case logic they might not need (if it were bundled in the package).

So if you want, we could do it this way and I would credit you on the demos page if you agree for it to be added there.

Hope that makes sense ๐Ÿ˜†

Regards,
Francisco Hodge

And what about having one mom package by layout? I think it could be more modular, more convenient for our need, and more lightweight bundles.
npm i -S simple-keyboard-ipad-layout could be really nice, and having a page acting as a registry links of all layouts.

Hmm I think that would be too granular in my opinion. Here's how I see it in terms of something being standalone or not:

  • Modules/plugins would go in their own repos, since they bring new features to simple-keyboard that I wouldn't want to bundle to core.
  • Ports, like react-simple-keyboard go in their own repos obviously.
  • Layouts would go together, since a layout file is generally very light (the whole package combined weighs under 3kb. Also having them together would encourage new language PRs like #17, since contributors wouldn't have to create a whole package.

And last, for the "use-cases". I think most people would edit them right away. That's why I provide them in a sandbox. For example, the fullKeyboard (which people often fork and remove the numpad lol) and darkTheme. These I think are more likely to be adapted by the users.

Another benefit of adding them to a sandbox is that I could just add more sandbox links for Angular, React, etc instead of making a package for every use-case.

image


If you'd like, I could add your iOS keyboard example to a sandbox and to the main demo, just so you see how it would be set. It'll get good visibility since the demo is where people normally get started.

Regards,
Francisco Hodge

Ok, so, if you agree, you can add the iOS iPad layout on the right demo place ๐Ÿ˜‰

Perfect, just added it to the demo
http://simple-keyboard.com/demo/#iOS

Thanks a lot for this sweet looking layout ๐Ÿ˜ƒ

Sorry I didn't gave you the full code! I've developed the entire behaviour (single tap and double tap on shift, reverting to lowercase if shift is not locked, etc.). Here is the full code (using react-simple-keyboard):

/* Some oversights from the css */
$keyboard-background-color: #d2d3db;
$keyboard-button-action-color: #adb5bc;
$keyboard-margins: 8px;
// Keyboard.js
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import SimpleKeyboard from 'react-simple-keyboard'

import { layout, display } from './layout'

import './index.scss' // the file I've already posted above.

const isFunctionButton = names => button => [...names].includes(button)
const isShiftButton = isFunctionButton(['{shift}', '{shiftactivated}'])
const isAltButton = isFunctionButton(['{alt}', '{altright}'])
const isSmileysButton = isFunctionButton(['{smileys}'])
const isDefaultButton = isFunctionButton(['{default}'])

class Keyboard extends Component {
  static propTypes = {
    onKeyPress: PropTypes.func
  }

  state = {
    layoutName: 'default',
    shiftActivated: false,
    shiftActivatedTime: null,
    shiftLocked: false
  }

  onKeyPress = button => {
    if (isShiftButton(button)) {
      this.shiftButtonPressLogic()
    } else if (isAltButton(button)) {
      this.handleAltButton()
    } else if (isDefaultButton(button)) {
      this.handleDefaultButton()
    } else if (isSmileysButton(button)) {
      this.handleSmileysButton()
    } else {
      this.genericButtonPressLogic(button)
    }
  }

  shiftButtonPressLogic = () => {
    const { state: { shiftLocked, shiftActivatedTime } } = this
    const now = Date.now()

    this.setState({ shiftActivated: true })

    if (!shiftLocked && shiftActivatedTime && now - shiftActivatedTime < 300) {
      this.setState({ shiftLocked: true })
    } else {
      this.setState({ shiftActivatedTime: now, shiftLocked: false })
      this.handleShiftButton()
    }
  }

  genericButtonPressLogic = button => {
    const { state: { layoutName, shiftLocked } } = this

    if (!shiftLocked) {
      const newLayoutName = layoutName !== 'shift' ? layoutName : 'default'

      this.setState({ shiftActivated: false, layoutName: newLayoutName })
    }

    if (typeof this.props.onKeyPress === 'function') {
      return this.props.onKeyPress(button)
    }
  }

  handleFunctionButton = ownLayoutName => this.setState(({ layoutName }) => ({ layoutName: layoutName !== ownLayoutName ? ownLayoutName : 'default' }))

  handleShiftButton = () => this.handleFunctionButton('shift')

  handleAltButton = () => this.handleFunctionButton('alt')

  handleSmileysButton = () => this.handleFunctionButton('smileys')

  handleDefaultButton = () => this.handleFunctionButton('default')

  render() {
    const { state: { layoutName }, onKeyPress } = this

    return (
      <SimpleKeyboard
        useTouchEvents
        onKeyPress={onKeyPress}
        physicalKeyboardHighlight
        layout={layout}
        layoutName={layoutName}
        display={display}
        mergeDisplay
      />
    )
  }
}
// layout.js
export const layout = {
  default: [
    'q w e r t y u i o p {bksp}',
    'a s d f g h j k l {enter}',
    '{shift} z x c v b n m , . {shift}',
    '{alt} {smileys} {space} {altright} {downkeyboard}'
  ],
  shift: [
    'Q W E R T Y U I O P {bksp}',
    'A S D F G H J K L {enter}',
    '{shiftactivated} Z X C V B N M , . {shiftactivated}',
    '{alt} {smileys} {space} {altright} {downkeyboard}'
  ],
  alt: [
    '1 2 3 4 5 6 7 8 9 0 {bksp}',
    `@ # $ & * ( ) ' " {enter}`,
    '{shift} % - + = / ; : ! ? {shift}',
    '{default} {smileys} {space} {back} {downkeyboard}'
  ],
  smileys: [
    '๐Ÿ˜€ ๐Ÿ˜Š ๐Ÿ˜… ๐Ÿ˜‚ ๐Ÿ™‚ ๐Ÿ˜‰ ๐Ÿ˜ ๐Ÿ˜› ๐Ÿ˜  ๐Ÿ˜Ž {bksp}',
    `๐Ÿ˜ ๐Ÿ˜ฌ ๐Ÿ˜ญ ๐Ÿ˜“ ๐Ÿ˜ฑ ๐Ÿ˜ช ๐Ÿ˜ฌ ๐Ÿ˜ด ๐Ÿ˜ฏ {enter}`,
    '๐Ÿ˜ ๐Ÿ˜‡ ๐Ÿคฃ ๐Ÿ˜˜ ๐Ÿ˜š ๐Ÿ˜† ๐Ÿ˜ก ๐Ÿ˜ฅ ๐Ÿ˜“ ๐Ÿ™„ {shift}',
    '{default} {smileys} {space} {altright} {downkeyboard}'
  ]
}

export const display = {
  '{bksp}': 'โŒซ',
  '{enter}': 'return',
  '{shift}': 'โ‡ง',
  '{shiftactivated}': 'โฌ†',
  '{alt}': '.?123',
  '{altright}': '.?123',
  '{smileys}': '๐Ÿ˜€',
  '{downkeyboard}': 'โ–ฟ',
  '{back}': 'โคบ',
  '{default}': 'ABC'
}

Awesome, so cool that you made the React version too. I'll make the updates to the demo later today and pass the status on here.

Cheers,
Francisco Hodge

Sorry for the delay, somehow I'm not able to getting this to work on a sandbox - If you have time, could you edit this sandbox and add in your changes?

If you don't have time - I could give it a try soon, just got my hands tied atm ๐Ÿ˜… I'll be closing this in the meantime.

Regards,
Francisco Hodge

Sorry for the delay, I was stuck on something else ๐Ÿ˜‰ I will do it soon!

I appreciate the time you've put in to improve these projects - There's no rush, and thanks again for the great contributions!

Your sandbox link is not correct ๐Ÿ˜•Should I create a new one?